ViewDragHelper实例学习笔记

来源:互联网 发布:宣传单页制作软件 编辑:程序博客网 时间:2024/05/17 21:53

github上的一个开源项目:https://github.com/BlueMor/DragLayout,

效果图:

侧滑效果的实现主要用的是ViewDragHelper,实现了对TouchEvent中的action处理进行了封装,

使用者不必操心在侧滑的过程中如何处理TouchEvent中的ACTION_DOWN、ACTION_MOVE和ACTION_UP事件,

而只需实现回调接口ViewDragHelper.Callback()中的方法就ok了,在此项目中实现的接口:

private ViewDragHelper.Callback dragHelperCallback = new ViewDragHelper.Callback() {   @Override        public boolean tryCaptureView(View child, int pointerId) {//当前view是否允许拖动            return true;        }    @Override        public int getViewHorizontalDragRange(View child) {<span style="font-family: Arial, Helvetica, sans-serif;">//横向拖动的最大距离</span>            return width;         }  @Override        public void onViewReleased(View releasedChild, float xvel, float yvel) {            super.onViewReleased(releasedChild, xvel, yvel);//ACTION_UP事件后调用其方法            if (xvel > 0) {                open();            } else if (xvel < 0) {                close();            } else if (releasedChild == vg_main && mainLeft > range * 0.3) {                open();            } else if (releasedChild == vg_left && mainLeft > range * 0.7) {                open();            } else {                close();            }        }        @Override        public int clampViewPositionHorizontal(View child, int left, int dx) {//返回横向坐标左右边界值            if (mainLeft + dx < 0) {                 return 0 ;//0            } else if (mainLeft + dx > range) {                return range;//            } else {                return left;            }        }    @Override        public void onViewPositionChanged(View changedView, int left, int top,                int dx, int dy) {//view在拖动过程坐标发生变化时会调用此方法,包括两个时间段:手动拖动和自动滚动                    if (changedView == vg_main) {            Log.d("draglayout","changedview is vg main");                mainLeft = left;            } else {                mainLeft = mainLeft + left;                Log.d("draglayout","changedview is vg left");            }            if (mainLeft < 0) {                mainLeft = 0;            } else if (mainLeft > range) {                mainLeft = range;            }            if (isShowShadow) {                iv_shadow.layout(mainLeft, 0, mainLeft + width, height);            }            if (changedView == vg_left) {                vg_left.layout(0, 0, width, height);                vg_main.layout(mainLeft, 0, mainLeft + width, height);            }            dispatchDragEvent(mainLeft);        }    };
在此接口中基本没有对touchevent事件的处理,那这些方法是怎么与touchevent时间联系起来的?

在touchevent事件处理中DragLayout是直接调用了ViewDragHelper中的processTouchEvent方法:

  public boolean onTouchEvent(MotionEvent e) {        try {            dragHelper.processTouchEvent(e);        } catch (Exception ex) {            ex.printStackTrace();        }        return false;    }

在processTouchEvent中对ACTION_DOWN、ACTION_MOVE和ACTION_UP事件进行了处理:

1.在ACTION_DOWN中调用回调接口中的tryCaptureView方法,看当前touch的view是否允许拖动

    在此项目中的是直接return true,两个view都是允许拖动的

2.在ACTION_MOVE中,view的坐标发生改变,调用回调接口中的onViewPositionChanged方法,

  根据坐标信息对view进行layout,通过ViewHelper这个类中的setScaleX、setScaleY方法,实现在

  拖动的过程中view在XY坐标上进行相应比例的缩放;

3.在ACTION_UP后调用回调接口中的onViewReleased方法,此方法中一个重要的任务是在ACTION_UP事件

  后,实现view的自动滑动,这里主要是使用了ViewDragHelper中smoothSlideViewTo方法,start了ViewDragHelper

  中的mScroller:

        mScroller.startScroll(startLeft, startTop, dx, dy, duration);        setDragState(STATE_SETTLING);
    然后通过方法ViewCompat.postInvalidateOnAnimation(this)调用view的 computeScroll() 方法:

    public void computeScroll() {        if (dragHelper.continueSettling(true)) {            ViewCompat.postInvalidateOnAnimation(this);        }    }

  ViewDragHelper的中的continueSettling方法会调用的mScroller.computeScrollOffset();方法,

来判断滚动是否结束,并在获取mScroller.getCurrX() 的值后,调用回调接口的onViewPositionChanged方法对view进行layout,

自此完成了手动拖和ACTION_UP后自动滚动的两个过程,大致流程图如下:






0 0
原创粉丝点击