From 10e2ee9d4f105d9737b98b1caacf5e6ccb1c3c7d Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Wed, 5 Jul 2017 12:51:21 -0700 Subject: Remap color dark and fix up swipe --- .../allanwang/kau/dialogs/color/ColorPickerView.kt | 2 +- .../ca/allanwang/kau/swipe/RelateSlider.java | 52 --- .../ca/allanwang/kau/swipe/RelativeSlider.kt | 36 ++ .../ca/allanwang/kau/swipe/SwipeBackHelper.java | 68 ---- .../ca/allanwang/kau/swipe/SwipeBackHelper.kt | 45 +++ .../ca/allanwang/kau/swipe/SwipeBackLayout.java | 438 --------------------- .../ca/allanwang/kau/swipe/SwipeBackLayout.kt | 312 +++++++++++++++ .../ca/allanwang/kau/swipe/SwipeBackPage.java | 120 ------ .../kotlin/ca/allanwang/kau/swipe/SwipeBackPage.kt | 66 ++++ .../ca/allanwang/kau/swipe/SwipeListener.java | 10 - .../kotlin/ca/allanwang/kau/swipe/SwipeListener.kt | 10 + .../kotlin/ca/allanwang/kau/utils/ColorUtils.kt | 13 +- sample/src/main/AndroidManifest.xml | 2 +- .../kotlin/ca/allanwang/kau/sample/AnimActivity.kt | 24 +- .../kotlin/ca/allanwang/kau/sample/MainActivity.kt | 2 +- 15 files changed, 502 insertions(+), 698 deletions(-) delete mode 100644 core/src/main/kotlin/ca/allanwang/kau/swipe/RelateSlider.java create mode 100644 core/src/main/kotlin/ca/allanwang/kau/swipe/RelativeSlider.kt delete mode 100644 core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackHelper.java create mode 100644 core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackHelper.kt delete mode 100644 core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackLayout.java create mode 100644 core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackLayout.kt delete mode 100644 core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackPage.java create mode 100644 core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackPage.kt delete mode 100644 core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeListener.java create mode 100644 core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeListener.kt diff --git a/core/src/main/kotlin/ca/allanwang/kau/dialogs/color/ColorPickerView.kt b/core/src/main/kotlin/ca/allanwang/kau/dialogs/color/ColorPickerView.kt index da864c9..20e0259 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/dialogs/color/ColorPickerView.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/dialogs/color/ColorPickerView.kt @@ -31,7 +31,7 @@ internal class ColorPickerView @JvmOverloads constructor( var isInCustom: Boolean = false var circleSize: Int = context.dimen(R.dimen.kau_color_circle_size).toInt() val backgroundColor = context.resolveColor(R.attr.md_background_color, - if (context.resolveColor(android.R.attr.textColorPrimary).isColorDark()) Color.WHITE else 0xff424242.toInt()) + if (context.resolveColor(android.R.attr.textColorPrimary).isColorDark) Color.WHITE else 0xff424242.toInt()) val backgroundColorTint = backgroundColor.colorToForeground() lateinit var dialog: MaterialDialog lateinit var builder: ColorContract diff --git a/core/src/main/kotlin/ca/allanwang/kau/swipe/RelateSlider.java b/core/src/main/kotlin/ca/allanwang/kau/swipe/RelateSlider.java deleted file mode 100644 index d438d00..0000000 --- a/core/src/main/kotlin/ca/allanwang/kau/swipe/RelateSlider.java +++ /dev/null @@ -1,52 +0,0 @@ -package ca.allanwang.kau.swipe; - -import android.os.Build; - -/** - * Created by Mr.Jude on 2015/8/26. - */ -public class RelateSlider implements SwipeListener { - public SwipeBackPage curPage; - private static final int DEFAULT_OFFSET = 40; - private int offset = 500; - - public RelateSlider(SwipeBackPage curActivity) { - this.curPage = curActivity; - //curPage.addListener(this); - } - - public void setOffset(int offset) { - this.offset = offset; - } - - public void setEnable(boolean enable){ - if (enable)curPage.addListener(this); - else curPage.removeListener(this); - } - - @Override - public void onScroll(float percent, int px) { - if (Build.VERSION.SDK_INT>11){ - SwipeBackPage page = SwipeBackHelper.getPrePage(curPage); - if (page!=null){ - page.getSwipeBackLayout().setX(Math.min(-offset * Math.max(1 - percent,0)+DEFAULT_OFFSET,0)); - if (percent == 0){ - page.getSwipeBackLayout().setX(0); - } - } - } - } - - @Override - public void onEdgeTouch() { - - } - - @Override - public void onScrollToClose() { - SwipeBackPage page = SwipeBackHelper.getPrePage(curPage); - if (Build.VERSION.SDK_INT>11) { - if (page != null) page.getSwipeBackLayout().setX(0); - } - } -} diff --git a/core/src/main/kotlin/ca/allanwang/kau/swipe/RelativeSlider.kt b/core/src/main/kotlin/ca/allanwang/kau/swipe/RelativeSlider.kt new file mode 100644 index 0000000..ee86ff2 --- /dev/null +++ b/core/src/main/kotlin/ca/allanwang/kau/swipe/RelativeSlider.kt @@ -0,0 +1,36 @@ +package ca.allanwang.kau.swipe + +import ca.allanwang.kau.kotlin.nonReadable + +/** + * Created by Mr.Jude on 2015/8/26. + */ +class RelativeSlider(var curPage: SwipeBackPage) : SwipeListener { + + var offset = 0f + + var enabled: Boolean + @Deprecated(level = DeprecationLevel.ERROR, message = "Cannot use enabled as getter") + get() = nonReadable() + set(value) { + if (value) curPage.addListener(this) + else curPage.removeListener(this) + } + + override fun onScroll(percent: Float, px: Int) { + if (offset == 0f) return //relative slider is not enabled + val page = SwipeBackHelper.getPrePage(curPage) ?: return + page.swipeBackLayout.x = Math.min(-offset * Math.max(1 - percent, 0f) + DEFAULT_OFFSET, 0f) + if (percent == 0f) page.swipeBackLayout.x = 0f + } + + override fun onEdgeTouch() {} + + override fun onScrollToClose() { + SwipeBackHelper.getPrePage(curPage)?.swipeBackLayout?.x = 0f + } + + companion object { + private const val DEFAULT_OFFSET = 40 + } +} diff --git a/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackHelper.java b/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackHelper.java deleted file mode 100644 index b72112e..0000000 --- a/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackHelper.java +++ /dev/null @@ -1,68 +0,0 @@ -package ca.allanwang.kau.swipe; - -import android.app.Activity; - -import java.util.Stack; - -/** - * 滑动的全局管理类 - */ -public class SwipeBackHelper { - - private static final Stack mPageStack = new Stack<>(); - - private static SwipeBackPage findHelperByActivity(Activity activity){ - for (SwipeBackPage swipeBackPage : mPageStack) { - if (swipeBackPage.mActivity == activity) return swipeBackPage; - } - return null; - } - - public static SwipeBackPage getCurrentPage(Activity activity){ - SwipeBackPage page; - if ((page = findHelperByActivity(activity)) == null){ - throw new RuntimeException("You Should call SwipeBackHelper.onCreate(activity) first"); - } - return page; - } - - public static void onCreate(Activity activity) { - SwipeBackPage page; - if ((page = findHelperByActivity(activity)) == null){ - page = mPageStack.push(new SwipeBackPage(activity)); - } - page.onCreate(); - } - - public static void onPostCreate(Activity activity){ - SwipeBackPage page; - if ((page = findHelperByActivity(activity)) == null){ - throw new RuntimeException("You Should call SwipeBackHelper.onCreate(activity) first"); - } - page.onPostCreate(); - } - - public static void onDestroy(Activity activity){ - SwipeBackPage page; - if ((page = findHelperByActivity(activity)) == null){ - throw new RuntimeException("You Should call SwipeBackHelper.onCreate(activity) first"); - } - mPageStack.remove(page); - page.mActivity=null; - } - - public static void finish(Activity activity){ - SwipeBackPage page; - if ((page = findHelperByActivity(activity)) == null){ - throw new RuntimeException("You Should call SwipeBackHelper.onCreate(activity) first"); - } - page.scrollToFinishActivity(); - } - - static SwipeBackPage getPrePage(SwipeBackPage activity){ - int index = mPageStack.indexOf(activity); - if (index>0)return mPageStack.get(index-1); - else return null; - } - -} diff --git a/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackHelper.kt b/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackHelper.kt new file mode 100644 index 0000000..4a8b6dc --- /dev/null +++ b/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackHelper.kt @@ -0,0 +1,45 @@ +package ca.allanwang.kau.swipe + +import android.app.Activity +import ca.allanwang.kau.logging.KL +import java.util.* + +class SwipeBackException(message: String = "You Should call SwipeBackHelper.onCreate(activity) first") : RuntimeException(message) + +object SwipeBackHelper { + + private val pageStack = Stack() + + private operator fun get(activity: Activity): SwipeBackPage + = pageStack.firstOrNull { it.activity === activity } ?: throw SwipeBackException() + + fun getCurrentPage(activity: Activity): SwipeBackPage = this[activity] + + fun onCreate(activity: Activity) { + pageStack.firstOrNull { it.activity === activity } ?: pageStack.push(SwipeBackPage(activity)) +// activity.window.exitTransition = + } + + fun onPostCreate(activity: Activity) = this[activity].onPostCreate() + + fun onDestroy(activity: Activity) { + KL.d("Swipe destroy") + val page: SwipeBackPage = this[activity] + pageStack.remove(page) + page.activity = null + } + + fun finish(activity: Activity) = this[activity].scrollToFinishActivity() + + internal fun getPrePage(activity: SwipeBackPage): SwipeBackPage? { + val index = pageStack.indexOf(activity) + return if (index > 0) pageStack[index - 1] else null + } + +} + +fun Activity.kauSwipeOnCreate() = SwipeBackHelper.onCreate(this) +fun Activity.kauSwipeOnPostCreate() = SwipeBackHelper.onPostCreate(this) +fun Activity.kauSwipeOnDestroy() = SwipeBackHelper.onDestroy(this) +fun Activity.kauSwipeFinish() = SwipeBackHelper.finish(this) + diff --git a/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackLayout.java b/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackLayout.java deleted file mode 100644 index 57195f2..0000000 --- a/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackLayout.java +++ /dev/null @@ -1,438 +0,0 @@ -package ca.allanwang.kau.swipe; - -import android.app.Activity; -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.Canvas; -import android.graphics.Rect; -import android.graphics.drawable.Drawable; -import android.support.v4.view.ViewCompat; -import android.support.v4.widget.ViewDragHelper; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewGroup; -import android.widget.FrameLayout; - -import java.util.ArrayList; -import java.util.List; - -public class SwipeBackLayout extends FrameLayout { - private static final String TAG = "ViewDragHelper"; - - /** - * Minimum velocity that will be detected as a fling - */ - private static final int MIN_FLING_VELOCITY = 400; // dips per second - - private static final int DEFAULT_SCRIM_COLOR = 0x99000000; - - private static final int FULL_ALPHA = 255; - - - /** - * A view is currently being dragged. The position is currently changing as - * a result of user input or simulated user input. - */ - public static final int STATE_DRAGGING = ViewDragHelper.STATE_DRAGGING; - - /** - * A view is currently settling into place as a result of a fling or - * predefined non-interactive motion. - */ - public static final int STATE_SETTLING = ViewDragHelper.STATE_SETTLING; - - /** - * Default threshold of scroll - */ - private static final float DEFAULT_SCROLL_THRESHOLD = 0.3f; - - private static final int OVERSCROLL_DISTANCE = 10; - - /** - * Threshold of scroll, we will close the activity, when scrollPercent over - * this value; - */ - private float mScrollThreshold = DEFAULT_SCROLL_THRESHOLD; - - private Activity mActivity; - - private boolean mEnable = true; - - private boolean mDisallowIntercept = false; - - private View mContentView; - - private ViewDragHelper mDragHelper; - - private float mScrollPercent; - - private int mContentLeft; - - /** - * The set of listeners to be sent events through. - */ - private List mListeners; - - Drawable mShadowLeft; - - private float mScrimOpacity; - - private int mScrimColor = DEFAULT_SCRIM_COLOR; - - private boolean mInLayout; - - private Rect mTmpRect = new Rect(); - - /** - * Edge being dragged - */ - private int mTrackingEdge; - - public SwipeBackLayout(Context context) { - this(context, null); - } - - public SwipeBackLayout(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public SwipeBackLayout(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs); - mDragHelper = ViewDragHelper.create(this, new ViewDragCallback()); - - setShadow(R.drawable.shadow_left); - - final float density = getResources().getDisplayMetrics().density; - final float minVel = MIN_FLING_VELOCITY * density; - setEdgeSize(getResources().getDisplayMetrics().widthPixels); - mDragHelper.setMinVelocity(minVel); - mDragHelper.setMaxVelocity(minVel * 2f); - mDragHelper.setSensitivity(context, 0.3f); - mDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT); - } - - /** - * Sets the sensitivity of the NavigationLayout. - * - * @param context The application context. - * @param sensitivity value between 0 and 1, the final value for touchSlop = - * ViewConfiguration.getScaledTouchSlop * (1 / s); - */ - public void setSensitivity(Context context, float sensitivity) { - mDragHelper.setSensitivity(context, sensitivity); - } - - /** - * Set up contentView which will be moved by user gesture - * - * @param view - */ - private void setContentView(View view) { - mContentView = view; - } - - public void setEnableGesture(boolean enable) { - mEnable = enable; - } - - /** - * Set a color to use for the scrim that obscures primary content while a - * drawer is open. - * - * @param color Color to use in 0xAARRGGBB format. - */ - public void setScrimColor(int color) { - mScrimColor = color; - invalidate(); - } - - /** - * Set the size of an edge. This is the range in pixels along the edges of - * this view that will actively detect edge touches or drags if edge - * tracking is enabled. - * - * @param size The size of an edge in pixels - */ - public void setEdgeSize(int size) { - mTrackingEdge = size; - mDragHelper.edsetEdgeSize(mTrackingEdge); - } - - - public void setEdgeSizePercent(float size) { - mTrackingEdge = (int) (getResources().getDisplayMetrics().widthPixels * size); - mDragHelper.setEdgeSize(mTrackingEdge); - } - - /** - * Register a callback to be invoked when a swipe event is sent to this - * view. - * - * @param listener the swipe listener to attach to this view - * @deprecated use {@link #addSwipeListener} instead - */ - @Deprecated - public void setSwipeListener(SwipeListener listener) { - addSwipeListener(listener); - } - - /** - * Add a callback to be invoked when a swipe event is sent to this view. - * - * @param listener the swipe listener to attach to this view - */ - public void addSwipeListener(SwipeListener listener) { - if (mListeners == null) { - mListeners = new ArrayList(); - } - mListeners.add(listener); - } - - /** - * Removes a listener from the set of listeners - * - * @param listener - */ - public void removeSwipeListener(SwipeListener listener) { - if (mListeners == null) { - return; - } - mListeners.remove(listener); - } - - - - /** - * Set scroll threshold, we will close the activity, when scrollPercent over - * this value - * - * @param threshold - */ - public void setScrollThreshold(float threshold) { - if (threshold >= 1.0f || threshold <= 0) { - throw new IllegalArgumentException("Threshold value should be between 0 and 1.0"); - } - mScrollThreshold = threshold; - } - - - public void setShadow(Drawable shadow) { - mShadowLeft = shadow; - invalidate(); - } - - - public void setShadow(int resId) { - setShadow(getResources().getDrawable(resId)); - } - - /** - * Scroll out contentView and finish the activity - */ - public void scrollToFinishActivity() { - final int childWidth = mContentView.getWidth(); - int left = 0, top = 0; - left = childWidth + mShadowLeft.getIntrinsicWidth() + OVERSCROLL_DISTANCE; - mDragHelper.smoothSlideViewTo(mContentView, left, top); - invalidate(); - } - - @Override - public boolean onInterceptTouchEvent(MotionEvent event) { - if (!mEnable||mDisallowIntercept) { - return false; - } - try { - return mDragHelper.shouldInterceptTouchEvent(event); - } catch (Exception e) { -// e.printStackTrace(); - return false; - } - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (!mEnable) { - return false; - } - try { - mDragHelper.processTouchEvent(event); - } catch (Exception e) { -// e.printStackTrace(); - return false; - } - return true; - } - - public void setDisallowInterceptTouchEvent(boolean disallowIntercept) { - mDisallowIntercept = disallowIntercept; - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - mInLayout = true; - if (mContentView != null) - mContentView.layout(mContentLeft, 0, - mContentLeft + mContentView.getMeasuredWidth(), - mContentView.getMeasuredHeight()); - mInLayout = false; - } - - @Override - public void requestLayout() { - if (!mInLayout) { - super.requestLayout(); - } - } - - @Override - protected boolean drawChild(Canvas canvas, View child, long drawingTime) { - final boolean drawContent = child == mContentView; - - boolean ret = super.drawChild(canvas, child, drawingTime); - if (mScrimOpacity > 0 && drawContent - && mDragHelper.getViewDragState() != ViewDragHelper.STATE_IDLE) { - drawShadow(canvas, child); - drawScrim(canvas, child); - } - return ret; - } - - private void drawScrim(Canvas canvas, View child) { - final int baseAlpha = (mScrimColor & 0xff000000) >>> 24; - final int alpha = (int) (baseAlpha * mScrimOpacity); - final int color = alpha << 24 | (mScrimColor & 0xffffff); - canvas.clipRect(0, 0, child.getLeft(), getHeight()); - canvas.drawColor(color); - } - - private void drawShadow(Canvas canvas, View child) { - final Rect childRect = mTmpRect; - child.getHitRect(childRect); - - mShadowLeft.setBounds(childRect.left - mShadowLeft.getIntrinsicWidth(), childRect.top, - childRect.left, childRect.bottom); - mShadowLeft.setAlpha((int) (mScrimOpacity * FULL_ALPHA)); - mShadowLeft.draw(canvas); - } - - public void attachToActivity(Activity activity) { - if (getParent()!=null){ - return; - } - mActivity = activity; - TypedArray a = activity.getTheme().obtainStyledAttributes(new int[]{ - android.R.attr.windowBackground - }); - int background = a.getResourceId(0, 0); - a.recycle(); - - ViewGroup decor = (ViewGroup) activity.getWindow().getDecorView(); - View decorChild = decor.findViewById(android.R.id.content); - while (decorChild.getParent() != decor){ - decorChild = (View) decorChild.getParent(); - } - decorChild.setBackgroundResource(background); - decor.removeView(decorChild); - addView(decorChild); - setContentView(decorChild); - decor.addView(this); - } - - public void removeFromActivity(Activity activity){ - if (getParent()==null)return; - ViewGroup decorChild = (ViewGroup) getChildAt(0); - ViewGroup decor = (ViewGroup) activity.getWindow().getDecorView(); - decor.removeView(this); - removeView(decorChild); - decor.addView(decorChild); - } - - @Override - public void computeScroll() { - mScrimOpacity = 1 - mScrollPercent; - if (mDragHelper.continueSettling(true)) { - ViewCompat.postInvalidateOnAnimation(this); - } - } - - private class ViewDragCallback extends ViewDragHelper.Callback { - private boolean mIsScrollOverValid; - - @Override - public boolean tryCaptureView(View view, int i) { - boolean ret = mDragHelper.isEdgeTouched(ViewDragHelper.EDGE_LEFT, i); - if (ret) { - if (mListeners != null && !mListeners.isEmpty()) { - for (SwipeListener listener : mListeners) { - listener.onEdgeTouch(); - } - } - mIsScrollOverValid = true; - } - return ret; - } - - @Override - public int getViewHorizontalDragRange(View child) { - return mTrackingEdge; - } - - @Override - public int getViewVerticalDragRange(View child) { - return 0; - } - - @Override - public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { - super.onViewPositionChanged(changedView, left, top, dx, dy); - mScrollPercent = Math.abs((float) left / (mContentView.getWidth() /*+ mShadowLeft.getIntrinsicWidth()*/)); - mContentLeft = left; - invalidate(); - if (mScrollPercent < mScrollThreshold && !mIsScrollOverValid) { - mIsScrollOverValid = true; - } - - if (mListeners != null && !mListeners.isEmpty()) { - for (SwipeListener listener : mListeners) { - listener.onScroll(mScrollPercent, mContentLeft); - } - } - if (mScrollPercent >= 1) { - if (!mActivity.isFinishing()){ - if (mListeners != null && !mListeners.isEmpty() - && mScrollPercent >= mScrollThreshold && mIsScrollOverValid) { - mIsScrollOverValid = false; - for (SwipeListener listener : mListeners) { - listener.onScrollToClose(); - } - } - mActivity.finish(); - } - } - - - } - - @Override - public void onViewReleased(View releasedChild, float xvel, float yvel) { - final int childWidth = releasedChild.getWidth(); - - int left = 0, top = 0; - //判断释放以后是应该滑到最右边(关闭),还是最左边(还原) - left = xvel > 0 || xvel == 0 && mScrollPercent > mScrollThreshold ? childWidth - + mShadowLeft.getIntrinsicWidth() + OVERSCROLL_DISTANCE : 0; - - - mDragHelper.settleCapturedViewAt(left, top); - invalidate(); - } - - @Override - public int clampViewPositionHorizontal(View child, int left, int dx) { - return Math.min(child.getWidth(), Math.max(left, 0)); - } - - } -} diff --git a/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackLayout.kt b/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackLayout.kt new file mode 100644 index 0000000..37dde73 --- /dev/null +++ b/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackLayout.kt @@ -0,0 +1,312 @@ +package ca.allanwang.kau.swipe + +import android.app.Activity +import android.content.Context +import android.graphics.Canvas +import android.graphics.Color +import android.support.v4.view.ViewCompat +import android.support.v4.widget.ViewDragHelper +import android.util.AttributeSet +import android.view.MotionEvent +import android.view.View +import android.view.ViewGroup +import android.widget.FrameLayout +import ca.allanwang.kau.utils.navigationBarColor +import ca.allanwang.kau.utils.statusBarColor +import java.lang.ref.WeakReference + +class SwipeBackLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0 +) : FrameLayout(context, attrs, defStyle), SwipeBackPageContract { + + override val swipeBackLayout: SwipeBackLayout + get() = this + /** + * Threshold of scroll, we will close the activity, when scrollPercent over + * this value; + */ + override var scrollThreshold = DEFAULT_SCROLL_THRESHOLD + set(value) { + if (value >= 1.0f || value <= 0) throw IllegalArgumentException("Threshold value should be between 0 and 1.0") + field = value + } + + var activity: Activity? = null + set(value) { + field = value + if (value != null) { + statusBarAlpha = Color.alpha(value.statusBarColor) + navBarAlpha = Color.alpha(value.navigationBarColor) + } + } + + override var swipeEnabled = true + + override var disallowIntercept = false + + private var contentView: View? = null + + private val dragHelper: ViewDragHelper + + private var scrollPercent: Float = 0.toFloat() + + private var contentOffset: Int = 0 + + /** + * The set of listeners to be sent events through. + */ + private var listeners: MutableList> = mutableListOf() + + private var scrimOpacity: Float = 0f + + override var scrimColor = DEFAULT_SCRIM_COLOR + /** + * Set a color to use for the scrim that obscures primary content while a + * drawer is open. + + * @param color Color to use in 0xAARRGGBB format. + */ + set(value) { + field = value + invalidate() + } + + var statusBarAlpha: Int = 255 + var navBarAlpha: Int = 255 + + val chromeFadeListener: SwipeListener by lazy { + object : SwipeListener { + override fun onScroll(percent: Float, px: Int) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun onEdgeTouch() { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun onScrollToClose() { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + } + } + + + private var inLayout: Boolean = false + + /** + * Edge being dragged + */ + private var trackingEdge: Int = 0 + + init { + dragHelper = ViewDragHelper.create(this, ViewDragCallback()) + val density = resources.displayMetrics.density + val minVel = MIN_FLING_VELOCITY * density + setEdgeSize(resources.displayMetrics.widthPixels) + dragHelper.minVelocity = minVel + dragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT) + } + + + /** + * Set up contentView which will be moved by user gesture + + * @param view + */ + private fun setContentView(view: View) { + contentView = view + } + + /** + * Set the size of an edge. This is the range in pixels along the edges of + * this view that will actively detect edge touches or drags if edge + * tracking is enabled. + + * @param swipeEdge The size of an edge in pixels + */ + override fun setEdgeSize(swipeEdge: Int) { + trackingEdge = swipeEdge + } + + + override fun setEdgeSizePercent(swipeEdgePercent: Float) { + trackingEdge = (resources.displayMetrics.widthPixels * swipeEdgePercent).toInt() + } + + /** + * Add a callback to be invoked when a swipe event is sent to this view. + + * @param listener the swipe listener to attach to this view + */ + override fun addListener(listener: SwipeListener) { + listeners.add(WeakReference(listener)) + } + + /** + * Removes a listener from the set of listeners + + * @param listener + */ + override fun removeListener(listener: SwipeListener) { + val iter = listeners.iterator() + while (iter.hasNext()) { + val l = iter.next().get() + if (l == null || l == listener) + iter.remove() + } + } + + /** + * Scroll out contentView and finish the activity + */ + override fun scrollToFinishActivity() { + val childWidth = contentView!!.width + val top = 0 + val left = childWidth + OVERSCROLL_DISTANCE + dragHelper.smoothSlideViewTo(contentView, left, top) + invalidate() + } + + override fun onInterceptTouchEvent(event: MotionEvent): Boolean { + if (!swipeEnabled || disallowIntercept) return false + val s = dragHelper.shouldInterceptTouchEvent(event) + return s + } + + override fun onTouchEvent(event: MotionEvent): Boolean { + if (!swipeEnabled) return false + dragHelper.processTouchEvent(event) + return true + } + + override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { + inLayout = true + contentView?.layout(contentOffset, 0, contentOffset + contentView!!.measuredWidth, contentView!!.measuredHeight) + inLayout = false + } + + override fun requestLayout() { + if (!inLayout) super.requestLayout() + } + + override fun drawChild(canvas: Canvas, child: View, drawingTime: Long): Boolean { + val drawContent = child === contentView + val ret = super.drawChild(canvas, child, drawingTime) + if (scrimOpacity > 0 && drawContent && dragHelper.viewDragState != ViewDragHelper.STATE_IDLE) + drawScrim(canvas, child) + return ret + } + + private fun drawScrim(canvas: Canvas, child: View) { + val baseAlpha = (scrimColor and 0xff000000.toInt()).ushr(24) + val alpha = (baseAlpha * scrimOpacity).toInt() + val color = alpha shl 24 or (scrimColor and 0xffffff) + canvas.clipRect(0, 0, child.left, height) + canvas.drawColor(color) + } + + fun attachToActivity(activity: Activity) { + if (parent != null) return + this.activity = activity + val a = activity.theme.obtainStyledAttributes(intArrayOf(android.R.attr.windowBackground)) + val background = a.getResourceId(0, 0) + a.recycle() + + val decor = activity.window.decorView as ViewGroup + var decorChild = decor.findViewById(android.R.id.content) + while (decorChild.parent !== decor) { + decorChild = decorChild.parent as View + } + decorChild.setBackgroundResource(background) + decor.removeView(decorChild) + addView(decorChild) + setContentView(decorChild) + decor.addView(this) + } + + fun removeFromActivity(activity: Activity) { + if (parent == null) return + val decorChild = getChildAt(0) as ViewGroup + val decor = activity.window.decorView as ViewGroup + decor.removeView(this) + removeView(decorChild) + decor.addView(decorChild) + } + + override fun computeScroll() { + scrimOpacity = 1 - scrollPercent + if (dragHelper.continueSettling(true)) ViewCompat.postInvalidateOnAnimation(this) + } + + private inner class ViewDragCallback : ViewDragHelper.Callback() { + private var isScrollOverValid: Boolean = false + + override fun tryCaptureView(view: View, i: Int): Boolean { + val ret = dragHelper.isEdgeTouched(ViewDragHelper.EDGE_LEFT, i) + if (ret) { + listeners.forEach { it.get()?.onEdgeTouch() } + isScrollOverValid = true + } + return ret + } + + override fun getViewHorizontalDragRange(child: View): Int { + return trackingEdge + } + + override fun getViewVerticalDragRange(child: View?): Int { + return 0 + } + + override fun onViewPositionChanged(changedView: View, left: Int, top: Int, dx: Int, dy: Int) { + super.onViewPositionChanged(changedView, left, top, dx, dy) + scrollPercent = Math.abs(left.toFloat() / contentView!!.width) + contentOffset = left + invalidate() + if (scrollPercent < scrollThreshold && !isScrollOverValid) + isScrollOverValid = true + + listeners.forEach { it.get()?.onScroll(scrollPercent, contentOffset) } + + if (scrollPercent >= 1) { + if (!(activity?.isFinishing ?: true)) { + if (scrollPercent >= scrollThreshold && isScrollOverValid) { + isScrollOverValid = false + listeners.forEach { it.get()?.onScrollToClose() } + } + activity?.finish() + } + } + } + + override fun onViewReleased(releasedChild: View, xvel: Float, yvel: Float) { + val childWidth = releasedChild.width + val top = 0 + val left = if (xvel > 0 || xvel == 0f && scrollPercent > scrollThreshold) + childWidth + OVERSCROLL_DISTANCE + else 0 + dragHelper.settleCapturedViewAt(left, top) + invalidate() + } + + override fun clampViewPositionHorizontal(child: View, left: Int, dx: Int): Int { + return Math.min(child.width, Math.max(left, 0)) + } + } + + companion object { + /** + * Minimum velocity that will be detected as a fling + */ + private const val MIN_FLING_VELOCITY = 400 // dips per second + + private const val DEFAULT_SCRIM_COLOR = 0x99000000.toInt() + + /** + * Default threshold of scroll + */ + private const val DEFAULT_SCROLL_THRESHOLD = 0.3f + + private const val OVERSCROLL_DISTANCE = 10 + } +} diff --git a/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackPage.java b/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackPage.java deleted file mode 100644 index 8afb5db..0000000 --- a/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackPage.java +++ /dev/null @@ -1,120 +0,0 @@ -package ca.allanwang.kau.swipe; - -import android.annotation.TargetApi; -import android.app.Activity; -import android.graphics.Color; -import android.graphics.drawable.ColorDrawable; -import android.view.ViewGroup; - -/** - * Created by Mr.Jude on 2015/8/3. - * 每个滑动页面的管理 - */ -public class SwipeBackPage { - //仅为判断是否需要将mSwipeBackLayout注入进去 - private boolean mEnable = true; - private boolean mRelativeEnable = false; - - Activity mActivity; - SwipeBackLayout mSwipeBackLayout; - RelateSlider slider; - SwipeBackPage(Activity activity){ - this.mActivity = activity; - } - - //页面的回调用于配置滑动效果 - void onCreate(){ - mActivity.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); - mActivity.getWindow().getDecorView().setBackgroundColor(Color.TRANSPARENT); - mSwipeBackLayout = new SwipeBackLayout(mActivity); - mSwipeBackLayout.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); - slider = new RelateSlider(this); - } - - void onPostCreate(){ - handleLayout(); - } - - - @TargetApi(11) - public SwipeBackPage setSwipeRelateEnable(boolean enable){ - mRelativeEnable = enable; - slider.setEnable(enable); - return this; - } - - public SwipeBackPage setSwipeRelateOffset(int offset){ - slider.setOffset(offset); - return this; - } - - //是否可滑动关闭 - public SwipeBackPage setSwipeBackEnable(boolean enable) { - mEnable = enable; - mSwipeBackLayout.setEnableGesture(enable); - handleLayout(); - return this; - } - - private void handleLayout(){ - if (mEnable||mRelativeEnable){ - mSwipeBackLayout.attachToActivity(mActivity); - }else { - mSwipeBackLayout.removeFromActivity(mActivity); - } - } - - //可滑动的范围。百分比。200表示为左边200px的屏幕 - public SwipeBackPage setSwipeEdge(int swipeEdge){ - mSwipeBackLayout.setEdgeSize(swipeEdge); - return this; - } - - //可滑动的范围。百分比。0.2表示为左边20%的屏幕 - public SwipeBackPage setSwipeEdgePercent(float swipeEdgePercent){ - mSwipeBackLayout.setEdgeSizePercent(swipeEdgePercent); - return this; - } - - //对横向滑动手势的敏感程度。0为迟钝 1为敏感 - public SwipeBackPage setSwipeSensitivity(float sensitivity){ - mSwipeBackLayout.setSensitivity(mActivity, sensitivity); - return this; - } - - //底层阴影颜色 - public SwipeBackPage setScrimColor(int color){ - mSwipeBackLayout.setScrimColor(color); - return this; - } - - //触发关闭Activity百分比 - public SwipeBackPage setClosePercent(float percent){ - mSwipeBackLayout.setScrollThreshold(percent); - return this; - } - - public SwipeBackPage setDisallowInterceptTouchEvent(boolean disallowIntercept){ - mSwipeBackLayout.setDisallowInterceptTouchEvent(disallowIntercept); - return this; - } - - public SwipeBackPage addListener(SwipeListener listener){ - mSwipeBackLayout.addSwipeListener(listener); - return this; - } - - public SwipeBackPage removeListener(SwipeListener listener){ - mSwipeBackLayout.removeSwipeListener(listener); - return this; - } - - public SwipeBackLayout getSwipeBackLayout() { - return mSwipeBackLayout; - } - - public void scrollToFinishActivity() { - mSwipeBackLayout.scrollToFinishActivity(); - } - -} diff --git a/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackPage.kt b/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackPage.kt new file mode 100644 index 0000000..e9a872b --- /dev/null +++ b/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeBackPage.kt @@ -0,0 +1,66 @@ +package ca.allanwang.kau.swipe + +import android.app.Activity +import android.graphics.Color +import android.graphics.drawable.ColorDrawable +import android.view.ViewGroup +import ca.allanwang.kau.logging.KL + +/** + * Created by Mr.Jude on 2015/8/3. + * 每个滑动页面的管理 + */ +class SwipeBackPage(activity: Activity) : SwipeBackPageContract by SwipeBackLayout(activity) { + + var activity: Activity? = activity + var slider: RelativeSlider + + /** + * initializing is the equivalent to onCreate + * since that is when the page is created + */ + init { + activity.window.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) + activity.window.decorView.setBackgroundColor(Color.TRANSPARENT) + swipeBackLayout.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + slider = RelativeSlider(this) + } + + fun onPostCreate() { + handleLayout() + } + + override var swipeEnabled: Boolean + get() = swipeBackLayout.swipeEnabled + set(value) { + swipeBackLayout.swipeEnabled = value + handleLayout() + } + + private fun handleLayout() { + KL.d("Handle layout") + if (swipeEnabled) swipeBackLayout.attachToActivity(activity!!) + else swipeBackLayout.removeFromActivity(activity!!) + } + + + //触发关闭Activity百分比 + fun setClosePercent(percent: Float): SwipeBackPage { + swipeBackLayout.scrollThreshold=percent + return this + } + +} + +interface SwipeBackPageContract { + var swipeEnabled: Boolean + var scrimColor:Int + val swipeBackLayout: SwipeBackLayout + var scrollThreshold:Float + var disallowIntercept:Boolean + fun setEdgeSize(swipeEdge: Int) + fun setEdgeSizePercent(swipeEdgePercent: Float) + fun addListener(listener: SwipeListener) + fun removeListener(listener: SwipeListener) + fun scrollToFinishActivity() +} diff --git a/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeListener.java b/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeListener.java deleted file mode 100644 index 6e67692..0000000 --- a/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeListener.java +++ /dev/null @@ -1,10 +0,0 @@ -package ca.allanwang.kau.swipe; - -public interface SwipeListener { - void onScroll(float percent,int px); - void onEdgeTouch(); - /** - * Invoke when scroll percent over the threshold for the first time - */ - void onScrollToClose(); - } \ No newline at end of file diff --git a/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeListener.kt b/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeListener.kt new file mode 100644 index 0000000..4fe9fa8 --- /dev/null +++ b/core/src/main/kotlin/ca/allanwang/kau/swipe/SwipeListener.kt @@ -0,0 +1,10 @@ +package ca.allanwang.kau.swipe + +interface SwipeListener { + fun onScroll(percent: Float, px: Int) + fun onEdgeTouch() + /** + * Invoke when scroll percent over the threshold for the first time + */ + fun onScrollToClose() +} \ No newline at end of file diff --git a/core/src/main/kotlin/ca/allanwang/kau/utils/ColorUtils.kt b/core/src/main/kotlin/ca/allanwang/kau/utils/ColorUtils.kt index 8590d6f..84a7c06 100644 --- a/core/src/main/kotlin/ca/allanwang/kau/utils/ColorUtils.kt +++ b/core/src/main/kotlin/ca/allanwang/kau/utils/ColorUtils.kt @@ -19,8 +19,8 @@ import com.afollestad.materialdialogs.R /** * Created by Allan Wang on 2017-06-08. */ -fun Int.isColorDark(): Boolean - = (0.299 * Color.red(this) + 0.587 * Color.green(this) + 0.114 * Color.blue(this)) / 255.0 < 0.5 +val Int.isColorDark: Boolean + get() = (0.299 * Color.red(this) + 0.587 * Color.green(this) + 0.114 * Color.blue(this)) / 255.0 < 0.5 fun Int.toHexString(withAlpha: Boolean = false, withHexPrefix: Boolean = true): String { val hex = if (withAlpha) String.format("#%08X", this) @@ -36,6 +36,9 @@ fun Int.toHSV(): FloatArray { return hsv } +inline val Int.isColorOpaque: Boolean + get() = Color.alpha(this) == 255 + fun FloatArray.toColor(): Int = Color.HSVToColor(this) fun Int.isColorVisibleOn(@ColorInt color: Int, @IntRange(from = 0L, to = 255L) delta: Int = 25, @@ -49,7 +52,7 @@ fun Int.isColorVisibleOn(@ColorInt color: Int, @IntRange(from = 0L, to = 255L) d @ColorInt fun Context.getDisabledColor(): Int { val primaryColor = resolveColor(android.R.attr.textColorPrimary) - val disabledColor = if (primaryColor.isColorDark()) Color.BLACK else Color.WHITE + val disabledColor = if (primaryColor.isColorDark) Color.BLACK else Color.WHITE return disabledColor.adjustAlpha(0.3f) } @@ -86,11 +89,11 @@ fun Int.darken(@FloatRange(from = 0.0, to = 1.0) factor: Float = 0.1f): Int { @ColorInt fun Int.colorToBackground(@FloatRange(from = 0.0, to = 1.0) factor: Float = 0.1f): Int - = if (isColorDark()) darken(factor) else lighten(factor) + = if (isColorDark) darken(factor) else lighten(factor) @ColorInt fun Int.colorToForeground(@FloatRange(from = 0.0, to = 1.0) factor: Float = 0.1f): Int - = if (isColorDark()) lighten(factor) else darken(factor) + = if (isColorDark) lighten(factor) else darken(factor) @Throws(IllegalArgumentException::class) fun String.toColor(): Int { diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml index 0ab360e..66b73c3 100644 --- a/sample/src/main/AndroidManifest.xml +++ b/sample/src/main/AndroidManifest.xml @@ -24,7 +24,7 @@ + android:theme="@style/Kau.Translucent" /> diff --git a/sample/src/main/kotlin/ca/allanwang/kau/sample/AnimActivity.kt b/sample/src/main/kotlin/ca/allanwang/kau/sample/AnimActivity.kt index fbcb88f..c2db025 100644 --- a/sample/src/main/kotlin/ca/allanwang/kau/sample/AnimActivity.kt +++ b/sample/src/main/kotlin/ca/allanwang/kau/sample/AnimActivity.kt @@ -1,10 +1,15 @@ package ca.allanwang.kau.sample import android.os.Bundle -import android.provider.MediaStore import android.support.v7.app.AppCompatActivity import ca.allanwang.kau.logging.KL -import ca.allanwang.kau.permissions.* +import ca.allanwang.kau.permissions.PERMISSION_ACCESS_COARSE_LOCATION +import ca.allanwang.kau.permissions.PERMISSION_ACCESS_FINE_LOCATION +import ca.allanwang.kau.permissions.kauOnRequestPermissionsResult +import ca.allanwang.kau.permissions.kauRequestPermissions +import ca.allanwang.kau.swipe.kauSwipeOnCreate +import ca.allanwang.kau.swipe.kauSwipeOnDestroy +import ca.allanwang.kau.swipe.kauSwipeOnPostCreate import ca.allanwang.kau.utils.fullLinearRecycler import ca.allanwang.kau.utils.startActivitySlideOut import ca.allanwang.kau.utils.toast @@ -35,6 +40,21 @@ class AnimActivity : AppCompatActivity() { } true } + kauSwipeOnCreate() + } + + override fun onPostCreate(savedInstanceState: Bundle?) { + super.onPostCreate(savedInstanceState) + kauSwipeOnPostCreate() + } + + override fun onDestroy() { + super.onDestroy() + kauSwipeOnDestroy() + } + + override fun finish() { + super.finish() } override fun onBackPressed() { diff --git a/sample/src/main/kotlin/ca/allanwang/kau/sample/MainActivity.kt b/sample/src/main/kotlin/ca/allanwang/kau/sample/MainActivity.kt index d0a5ee1..1f2d757 100644 --- a/sample/src/main/kotlin/ca/allanwang/kau/sample/MainActivity.kt +++ b/sample/src/main/kotlin/ca/allanwang/kau/sample/MainActivity.kt @@ -210,7 +210,7 @@ class MainActivity : KPrefActivity() { override fun onOptionsItemSelected(item: MenuItem): Boolean { when (item.itemId) { - R.id.action_settings -> startActivity(AnimActivity::class.java, clearStack = true) + R.id.action_settings -> startActivity(AnimActivity::class.java) R.id.action_email -> sendEmail(R.string.your_email, R.string.your_subject) R.id.test -> startActivity(ImageActivity::class.java, transition = true) else -> return super.onOptionsItemSelected(item) -- cgit v1.2.3