package yifeiyuan.practice.practicedemos.viewdrager; import android.content.Context; import android.support.v4.widget.ViewDragHelper; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.widget.LinearLayout; /** * Created by alanchen on 15/7/14. * * onFinishInflate * onAttachedToWindow * onMeasure * onLayout * onMeasure * onLayout * * * 一般流程: return * tryCaptureView true * onViewCaptured * 一直move:clampViewPositionVertical/clampViewPositionHorizontal left/top值 * up:onViewReleased */ public class DragerView extends LinearLayout { public static final String TAG = DragerView.class.getSimpleName(); private ViewDragHelper mDragHelper; public DragerView(Context context) { this(context, null); } public DragerView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public DragerView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private int originLeft; private int originTop; private void init() { mDragHelper = ViewDragHelper.create(this, 1f, new ViewDragHelper.Callback() { /** * * @param child 用户想要拖动的view * @param pointerId * @return true 代表可以拖动 */ @Override public boolean tryCaptureView(View child, int pointerId) { Log.d(TAG, "tryCaptureView() called with " + "child = [" + child + "], pointerId = [" + pointerId + "]"); return child == mNormal || child == mAutoBack||child == mClickableView; } /** * 当某个view 被captured 后会被调用 * @param capturedChild * @param activePointerId */ @Override public void onViewCaptured(View capturedChild, int activePointerId) { Log.d(TAG, "onViewCaptured() called with " + "capturedChild = [" + capturedChild + "], activePointerId = [" + activePointerId + "]"); super.onViewCaptured(capturedChild, activePointerId); } /** * 水平固定? * 限制子view * * @param child 移动的view * @param left 即将移动到的位置 以此确定x轴的位置 * @param dx 差值 从5 ~8 那么dx就是3 * @return */ @Override public int clampViewPositionHorizontal(View child, int left, int dx) { Log.d(TAG, "clampViewPositionHorizontal() called with " + "left = [" + left + "], dx = [" + dx + "]"); int leftbound = getPaddingLeft(); int rightbound = mWidth - getPaddingRight() - child.getWidth(); // return Math.max(left,0);//感觉像是整个坐标系 在 整个屏幕上 return Math.min(Math.max(leftbound, left), rightbound); } @Override public int clampViewPositionVertical(View child, int top, int dy) { Log.d(TAG, "clampViewPositionVertical() called with " + "top = [" + top + "], dy = [" + dy + "]"); return top; } @Override public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { Log.d(TAG, "onViewPositionChanged() called with " + "changedView = [" + changedView + "], left = [" + left + "], top = [" + top + "], dx = [" + dx + "], dy = [" + dy + "]"); super.onViewPositionChanged(changedView, left, top, dx, dy); } @Override public void onViewReleased(View releasedChild, float xvel, float yvel) { Log.d(TAG, "onViewReleased() called with " + "releasedChild = [" + releasedChild + "], xvel = [" + xvel + "], yvel = [" + yvel + "]"); super.onViewReleased(releasedChild, xvel, yvel); if (releasedChild == mAutoBack) { //Notice 其实 就是scroller.startScroll 所以记得要invalidate 还要重写 computeScroll mDragHelper.settleCapturedViewAt(originLeft, originTop); invalidate(); } } /** * 拖动状态改变 * @see ViewDragHelper#STATE_IDLE 0 停止 * STATE_DRAGGING 1 正在被拖动 * STATE_SETTLING 2 自动移动? * @param state */ @Override public void onViewDragStateChanged(int state) { Log.d(TAG, "onViewDragStateChanged() called with " + "state = [" + state + "]"); super.onViewDragStateChanged(state); } /** * 当被订阅的边界被touch 时 触发 * @param edgeFlags * @param pointerId */ @Override public void onEdgeTouched(int edgeFlags, int pointerId) { Log.d(TAG, "onEdgeTouched() called with " + "edgeFlags = [" + edgeFlags + "], pointerId = [" + pointerId + "]"); super.onEdgeTouched(edgeFlags, pointerId); //Notice captureChildView 强制capture 无视try if (ViewDragHelper.EDGE_LEFT == edgeFlags) { mDragHelper.captureChildView(mEdgeLeft, pointerId); } else if (ViewDragHelper.EDGE_RIGHT == edgeFlags) { mDragHelper.captureChildView(mEdgeRight, pointerId); } } @Override public boolean onEdgeLock(int edgeFlags) { Log.d(TAG, "onEdgeLock() called with " + "edgeFlags = [" + edgeFlags + "]"); return super.onEdgeLock(edgeFlags); } @Override public void onEdgeDragStarted(int edgeFlags, int pointerId) { Log.d(TAG, "onEdgeDragStarted() called with " + "edgeFlags = [" + edgeFlags + "], pointerId = [" + pointerId + "]"); super.onEdgeDragStarted(edgeFlags, pointerId); } @Override public int getOrderedChildIndex(int index) { Log.d(TAG, "getOrderedChildIndex() called with " + "index = [" + index + "]"); return super.getOrderedChildIndex(index); } /** * Notice 当想要拖动的子view 有点击事件的时候需要重写 * Notice 想在水平上能拖动 getViewHorizontalDragRange 需要return 一个>0的数 * Notice 同理 垂直: getViewVerticalDragRange 也需要return 一个>0的数 * @param child * @return */ @Override public int getViewHorizontalDragRange(View child) { Log.d(TAG, "getViewHorizontalDragRange() called with " + "child = [" + child + "]"); // return super.getViewHorizontalDragRange(child); return 1; } /** * @param child * @return */ @Override public int getViewVerticalDragRange(View child) { Log.d(TAG, "getViewVerticalDragRange() called with " + "child = [" + child + "]"); // return super.getViewVerticalDragRange(child); return 1; } }); /** * 订阅边界触发 * 当用户触摸边界 会触发 onEdgeTouched */ mDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT | ViewDragHelper.EDGE_RIGHT); } @Override public void computeScroll() { super.computeScroll(); if (mDragHelper.continueSettling(true)) { invalidate(); } } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { Log.d(TAG, "onInterceptTouchEvent() called with " + "ev = [" + ev + "]"); return mDragHelper.shouldInterceptTouchEvent(ev); // mDragHelper.shouldInterceptTouchEvent(ev); // return true; } @Override public boolean onTouchEvent(MotionEvent event) { Log.d(TAG, "onTouchEvent() called with " + "event = [" + event + "]"); mDragHelper.processTouchEvent(event); // return super.onTouchEvent(event); return true; } private View mNormal; private View mAutoBack; private View mEdgeLeft; private View mEdgeRight; private View mClickableView; @Override protected void onFinishInflate() { super.onFinishInflate(); Log.d(TAG, "onFinishInflate "); mNormal = getChildAt(0); mAutoBack = getChildAt(1); mEdgeLeft = getChildAt(2); mEdgeRight = getChildAt(3); mClickableView = getChildAt(4); } private int mHeight; private int mWidth; @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); Log.d(TAG, "onLayout "); mWidth = getWidth(); mHeight = getHeight(); originLeft = mAutoBack.getLeft(); originTop = mAutoBack.getTop(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); Log.d(TAG, "onMeasure "); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); Log.d(TAG, "onAttachedToWindow "); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); Log.d(TAG, "onDetachedFromWindow "); } }