使用ViewDragHelper来现实自定义DrawerLayout

来源:互联网 发布:淘宝网店培训视频 编辑:程序博客网 时间:2024/05/29 03:41

侧拉效果在Android中已经司空见惯了,实现的方案也有很多种选择,比如官方控件DrawerLayout,SlidingPaneLayout,还有一些著名的第三方控件SlideMenu。

这篇博客主要是介绍用ViewDragHelper来现实侧拉效果(自定义控件),当然自定义控件实现侧拉也不一定要用ViewDragHelper。比如使用改变MarginLayoutParams的Margin的值一样能实现,但是为什么用ViewDragHelper呢?因为使用它来现实侧拉等一些滑动效果极其方便,免去了一些处理touch细节的工作。像官方控件DrawerLayout,SlidingPaneLayout内部用的也是ViewDragHelper,当然官方控件更加强大的多,例子只是实现最简单的侧拉,线上代码:

public class MyDrawerlayout extends FrameLayout {    private ViewDragHelper mHelper;    private View menuView, mainView;    private int mMenuWith;    private ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {        /**         * 处理mainView的滑动         * @param child         * @param pointerId         * @return         */        @Override        public boolean tryCaptureView(View child, int pointerId) {            return child == mainView;        }        /**         * 处理水平滑动         * @param child         * @param left         * @param dx         * @return         */        @Override        public int clampViewPositionHorizontal(View child, int left, int dx) {            if (left < 0)                return 0;            if (left > mMenuWith)                return  mMenuWith;            return left;        }        /**         * 处理垂直滑动         * @param child         * @param top         * @param dy         * @return         */        @Override        public int clampViewPositionVertical(View child, int top, int dy) {            return 0;        }        @Override        public void onViewReleased(View releasedChild, float xvel, float yvel) {            super.onViewReleased(releasedChild, xvel, yvel);            if (mainView.getLeft()<mMenuWith/2){//关闭menu                mHelper.smoothSlideViewTo(mainView,0,0);                ViewCompat.postInvalidateOnAnimation(MyDrawerlayout.this);            }else{//打开menu                mHelper.smoothSlideViewTo(mainView,mMenuWith,0);                ViewCompat.postInvalidateOnAnimation(MyDrawerlayout.this);            }        }    };    public MyDrawerlayout(Context context, AttributeSet attrs) {        super(context, attrs);        init();    }    public MyDrawerlayout(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init();    }    public MyDrawerlayout(Context context) {        super(context);        init();    }    /**     * 一些初始化工作     */    private void init() {        mHelper = ViewDragHelper.create(this, callback);    }    /**     * 加载完成xml     */    @Override    protected void onFinishInflate() {        super.onFinishInflate();        //默认第一个为menu,第二个是main        menuView = getChildAt(0);        mainView = getChildAt(1);    }    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        mMenuWith = menuView.getMeasuredWidth();    }    @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        return mHelper.shouldInterceptTouchEvent(ev);    }    @Override    public boolean onTouchEvent(MotionEvent event) {        mHelper.processTouchEvent(event);        return true;    }    /**     *  必须重写,因为viewdraghelper内部用的也是scroller原理,重写onViewReleased就必须重写computeScroll     */    @Override    public void computeScroll() {        super.computeScroll();        if (mHelper.continueSettling(true)){            ViewCompat.postInvalidateOnAnimation(this);        }    }}

布局文件:

<?xml version="1.0" encoding="utf-8"?><com.ailingke.androidscrolllearning.views.MyDrawerlayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    >    <TextView        android:layout_width="200dp"        android:layout_height="match_parent"        android:background="#FF0000"/>    <TextView        android:layout_width="match_parent"        android:layout_height="match_parent"        android:background="#00FF00"/></com.ailingke.androidscrolllearning.views.MyDrawerlayout>

使用ViewDragHelper分几步:
①获取ViewGragHelper实例:我们通过使用ViewDragHelper的一个静态方法来创建实例:

ViewDragHelper create(ViewGroup forParent, float sensitivity, Callback cb)ViewDragHelper create(ViewGroup forParent, Callback cb)

②拦截事件(把触摸事件都交给ViewDragHelper来处理)

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

③重写computeScroll(因为ViewDragHelper内部也是通过Scroller来现实平滑的移动,如果CallBack中重写onViewReleased方法,就必须重写)
模板代码如下:

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

④最后一步,也是最为重要的一步,实现ViewDargHelper.CallBack对象。在ViewDragHelper.Callback中,系统定义了大量的监听事件来帮助我们处理各种事件。
例子中重写的
public boolean tryCaptureView(View child, int pointerId)
指定需要处理的子view
public int clampViewPositionHorizontal(View child, int left, int dx)
处理水平滑动
public int clampViewPositionVertical(View child, int top, int dy)
处理垂直滑动
public void onViewReleased(View releasedChild, float xvel, float yvel)
释放时回调
此外还有一些,一共13个回调函数。

ViewDragHelper功能很强大,但是使用时需要一些基础,只有不断的使用它来现实从简到难的自定义控件才能更好的掌握它。

0 0
原创粉丝点击