1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
| public class SwipeBackLayout extends FrameLayout { * Edge flag indicating that the left edge should be affected. */ public static final int EDGE_LEFT = ViewDragHelper.EDGE_LEFT;
* Edge flag indicating that the right edge should be affected. */ public static final int EDGE_RIGHT = ViewDragHelper.EDGE_RIGHT;
* Edge flag indicating that the bottom edge should be affected. */ public static final int EDGE_BOTTOM = ViewDragHelper.EDGE_BOTTOM;
* Edge flag set indicating all edges should be affected. */ public static final int EDGE_ALL = EDGE_LEFT | EDGE_RIGHT | EDGE_BOTTOM; * Default threshold of scroll * 超过0.3f的屏幕比例的距离之后可以滑动出去了,临界值是0.3f */ private static final float DEFAULT_SCROLL_THRESHOLD = 0.3f;
private static final int OVERSCROLL_DISTANCE = 10;
private float mScrimOpacity;
* Edge being dragged */ private int mTrackingEdge; private float mScrollPercent;
private int mContentLeft;
private int mContentTop; * Threshold of scroll, we will close the activity, when scrollPercent over * this value; */ private float mScrollThreshold = DEFAULT_SCROLL_THRESHOLD;
private class ViewDragCallback extends ViewDragHelper.Callback { private boolean mIsScrollOverValid;
@Override public boolean tryCaptureView(View view, int i) { boolean ret = mDragHelper.isEdgeTouched(mEdgeFlag, i); if (ret) { if (mDragHelper.isEdgeTouched(EDGE_LEFT, i)) { mTrackingEdge = EDGE_LEFT; } else if (mDragHelper.isEdgeTouched(EDGE_RIGHT, i)) { mTrackingEdge = EDGE_RIGHT; } else if (mDragHelper.isEdgeTouched(EDGE_BOTTOM, i)) { mTrackingEdge = EDGE_BOTTOM; } if (mListeners != null && !mListeners.isEmpty()) { for (SwipeListener listener : mListeners) { listener.onEdgeTouch(mTrackingEdge); } } mIsScrollOverValid = true; } boolean directionCheck = false; if (mEdgeFlag == EDGE_LEFT || mEdgeFlag == EDGE_RIGHT) { directionCheck = !mDragHelper.checkTouchSlop(ViewDragHelper.DIRECTION_VERTICAL, i); } else if (mEdgeFlag == EDGE_BOTTOM) { directionCheck = !mDragHelper .checkTouchSlop(ViewDragHelper.DIRECTION_HORIZONTAL, i); } else if (mEdgeFlag == EDGE_ALL) { directionCheck = true; } return ret & directionCheck; }
@Override public int getViewHorizontalDragRange(View child) { return mEdgeFlag & (EDGE_LEFT | EDGE_RIGHT); }
@Override public int getViewVerticalDragRange(View child) { return mEdgeFlag & EDGE_BOTTOM; }
@Override public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { super.onViewPositionChanged(changedView, left, top, dx, dy); if ((mTrackingEdge & EDGE_LEFT) != 0) { mScrollPercent = Math.abs((float) left / (mContentView.getWidth() + mShadowLeft.getIntrinsicWidth())); } else if ((mTrackingEdge & EDGE_RIGHT) != 0) { mScrollPercent = Math.abs((float) left / (mContentView.getWidth() + mShadowRight.getIntrinsicWidth())); } else if ((mTrackingEdge & EDGE_BOTTOM) != 0) { mScrollPercent = Math.abs((float) top / (mContentView.getHeight() + mShadowBottom.getIntrinsicHeight())); } mContentLeft = left; mContentTop = top; invalidate(); if (mScrollPercent < mScrollThreshold && !mIsScrollOverValid) { mIsScrollOverValid = true; } if (mListeners != null && !mListeners.isEmpty() && mDragHelper.getViewDragState() == STATE_DRAGGING && mScrollPercent >= mScrollThreshold && mIsScrollOverValid) { mIsScrollOverValid = false; for (SwipeListener listener : mListeners) { listener.onScrollOverThreshold(); } } if (mScrollPercent >= 1) { if (!mActivity.isFinishing()) { mActivity.finish(); mActivity.overridePendingTransition(0, 0); } } } @Override public void onViewReleased(View releasedChild, float xvel, float yvel) { final int childWidth = releasedChild.getWidth(); final int childHeight = releasedChild.getHeight();
int left = 0, top = 0; if ((mTrackingEdge & EDGE_LEFT) != 0) { left = xvel > 0 || xvel == 0 && mScrollPercent > mScrollThreshold ? childWidth + mShadowLeft.getIntrinsicWidth() + OVERSCROLL_DISTANCE : 0; } else if ((mTrackingEdge & EDGE_RIGHT) != 0) { left = xvel < 0 || xvel == 0 && mScrollPercent > mScrollThreshold ? -(childWidth + mShadowLeft.getIntrinsicWidth() + OVERSCROLL_DISTANCE) : 0; } else if ((mTrackingEdge & EDGE_BOTTOM) != 0) { top = yvel < 0 || yvel == 0 && mScrollPercent > mScrollThreshold ? -(childHeight + mShadowBottom.getIntrinsicHeight() + OVERSCROLL_DISTANCE) : 0; } mDragHelper.settleCapturedViewAt(left, top); invalidate(); } @Override public int clampViewPositionHorizontal(View child, int left, int dx) { int ret = 0; if ((mTrackingEdge & EDGE_LEFT) != 0) { ret = Math.min(child.getWidth(), Math.max(left, 0)); } else if ((mTrackingEdge & EDGE_RIGHT) != 0) { ret = Math.min(0, Math.max(left, -child.getWidth())); } return ret; }
@Override public int clampViewPositionVertical(View child, int top, int dy) { int ret = 0; if ((mTrackingEdge & EDGE_BOTTOM) != 0) { ret = Math.min(0, Math.max(top, -child.getHeight())); } return ret; }
@Override public void onViewDragStateChanged(int state) { super.onViewDragStateChanged(state); if (mListeners != null && !mListeners.isEmpty()) { for (SwipeListener listener : mListeners) { listener.onScrollStateChange(state, mScrollPercent); } } } } @Override public void computeScroll() { mScrimOpacity = 1 - mScrollPercent; if (mDragHelper.continueSettling(true)) { ViewCompat.postInvalidateOnAnimation(this); } } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { mInLayout = true; if (mContentView != null) { mContentView.layout(mContentLeft, mContentTop, mContentLeft + mContentView.getMeasuredWidth(), mContentTop + mContentView.getMeasuredHeight()); } mInLayout = false; } @Override public void requestLayout() { if (!mInLayout) { super.requestLayout(); } } }
|