Android-ViewDragHelper

ViewDragHelper


我们都知道在Google发布的support包中包含了DrawerLayout和SlidingPaneLayout这两个可以滑动的控件,其实这两个布局背后就隐藏着ViewDragHelper。通过ViewDragHelper基本上的滑动需求都可以满足,所以这个方法是各种滑动解决方案的终极绝招

下面我们来进行一个实例,来使用一下ViewDragHelper,类似于QQ的侧滑菜单。废话不多说,上图:

Android-ViewDragHelper_第1张图片

使用ViewDragHelper

  1. 初始化ViewDragHelper
  2. 重写拦截、触摸事件交给ViewDragHelper处理
  3. 处理computeScroll()
  4. 处理回调接口Callback

初始化ViewDragHelper

ViewDragHelper通常定义在一个ViewGroup的内部,并通过静态工厂方法进行初始化,代码如下:

mHelper = ViewDragHelper.create(this, callback);

对,就这一行代码,这里的this就是只一个ViewGroup了,callback就是刚才我们说的回调接口

重写拦截、触摸事件交给ViewDragHelper处理

@Override
public boolean onTouchEvent(MotionEvent event) {
    mHelper.processTouchEvent(event);
    return true;
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    return mHelper.shouldInterceptTouchEvent(ev);
}

这里就是一个事件拦截和触摸事件监听,上一文中都讲过,这里不在多说,就是调用了DragViewHelper的两个方法而已

处理computeScroll()

因为ViewDragHelper也是通过Scroller来实现平滑移动的,所以我们要重写computeScroll()方法,一般代码如下:

@Override
public void computeScroll() {
    if (mHelper.continueSettling(true)) {
        ViewCompat.postInvalidateOnAnimation(this);
    }
}

处理回调接口Callback

处理回调接口就是最关键的代码了,我们一般需要重写这几个方法

  • tryCaptureView
    • 这个方法是自动创建的,通过这个方法可以指定哪一个子View可以移动
  • clampViewPositionHorizontal
    • 这个方法对应的是水平上的滑动
  • clampViewPositionVertical
    • 这个方法对应的是垂直上的滑动
    • 如果想要滑动,这两个方法是必须要重写其中一个或者全部重写的,因为方法默认返回0,即不发生滑动
  • onViewReleased
    • 这个方法在手指离开屏幕后调用

不多说,直接把代码撸上来,非常简单,对照注释一看就懂,整体代码如下

public class ViewDragHelperDemo extends FrameLayout {

    ViewDragHelper mHelper;
    View mainView, menuView;

    public ViewDragHelperDemo(Context context) {
        this(context, null);
    }

    public ViewDragHelperDemo(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ViewDragHelperDemo(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        /**
         * 初始化ViewDragHelper
         */
        mHelper = ViewDragHelper.create(this, callback);
    }


    ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {
        @Override
        public boolean tryCaptureView(View child, int pointerId) {
            /**
             * 决定滑动的View
             */
            return child == mainView;
        }

        @Override
        public int clampViewPositionHorizontal(View child, int left, int dx) {
            /**
             * 水平方向上的移动
             */
            return left;
        }

        @Override
        public void onViewReleased(View releasedChild, float xvel, float yvel) {
            super.onViewReleased(releasedChild, xvel, yvel);
            /**
             * 当手指离开屏幕后,如果当前移动的View和父布局之间的距离小于150,那么则移动回原位
             * 如果大于150,那么则滑动到300
             */
            if (mainView.getLeft() < 150) {
                mHelper.smoothSlideViewTo(mainView, 0, 0);
            }else{
                mHelper.smoothSlideViewTo(mainView, 300, 0);
            }

            /**
             * 通知重绘
             */
            ViewCompat.postInvalidateOnAnimation(DragViewHelperDemo.this);
        }
    };

    /**
     * 此方法会在布局加载完毕调用,我们把第一个布局设置为menuView,第二个设置为mainView
     */
    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        menuView = getChildAt(0);
        mainView = getChildAt(1);
    }

    /**
     * 这里设置触摸/拦截事件给DragViewHelper
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mHelper.processTouchEvent(event);
        return true;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return mHelper.shouldInterceptTouchEvent(ev);
    }

    /**
     * 设置computeScroll
     */
    @Override
    public void computeScroll() {
        if (mHelper.continueSettling(true)) {
            ViewCompat.postInvalidateOnAnimation(this);
        }
    }
}

运行程序,就会看到和上面一样的效果啦。ViewDragHelper是最麻烦的一种,但是多写一写就好啦~


最后

爱生活,爱小丽,爱Android

你可能感兴趣的:(Android-ViewDragHelper)