android ViewDragHelper 实现抽屉滑动效果

                      

今天我要来讲解一个比较常见的效果 就是抽屉式菜单 当滑动图片的黄色部分 隐藏在底下下的蓝色菜单栏就会被显示出来 在谷歌2013大会上 公布了一个 DrawerLayout 用来实现类似的效果 在此之前 基本上要在项目里面使用 都是几月github上第三方的控件  最近研究了一个 非常有用却很少有人知道的view滑动处理类 ViewDragHelper 像在官方提供的 DrawerLayout 和PanelLayout中对拖拽和滑动时间的出来都是 基于ViewDragHelper 来实现的

之前自己也实现过类似的抽屉的效果 当时的实现方式是继承HorizontalScrollView来实现的   在HorizontalScrollView中提供了滑动的事件以及对冲突的处理 有兴趣的同学可以自己来实现看看

而今天我们要用 ViewDragHelper来实现这个效果

首先我们要明白 ViewDragHelper 只能作用于一个ViewGroup并对其中的子View的滑动进行处理 所以这里我们需要自定义一个view 改view继承自FrameLayout 因为抽屉式的菜单总是在内容view之下的 这个正好符合

首先需要定义ViewDragHelper

 mDragHelper = ViewDragHelper.create(this, 1.0f, new DragHelperCallBack());

ViewDragHelper 中提供一个静态的方法来创建对象。第一个参数表示的是一个父布局 第二个参数表示敏感度 第三个参数是一个回调接口 ViewDragHelper.Callback 是和View 通讯的桥梁 大部分的动画效果都是在这里实现的 其中的回调函数也很多 这里我们只用了其中几个:

@Override
        public boolean tryCaptureView(View arg0, int arg1) {
            return arg0==childView;
        }

以上方法是用来处理那个view 是可以滑动的 返回为true 是全部可滑动

@Override
        public int clampViewPositionHorizontal(View child, int left, int dx) {
            if(left <= 0)
                return 0;
            if(left >= mMenuWidth)
                return mMenuWidth;
            
            return left;
        }

以上方法是用来处理横向滑动的 返回的值是滑动的距离 这里我们处理了最小滑动的坐标是0 最大为menu的宽度

@Override
        public int getViewHorizontalDragRange(View child) {
            return mMenuWidth;
        }

以上方法是返回最大的横向的滑动的距离

@Override
        public void onViewReleased(View releasedChild, float xvel, float yvel) {
            super.onViewReleased(releasedChild, xvel, yvel);
            Log.i("result",releasedChild.getLeft()+"");
            
            if(mState==STATE.close){
                if(releasedChild.getLeft()>=(mMenuWidth/2)){
                    open();
                }else{
                    close();
                }
            }
            if(mState==STATE.open){
                if(releasedChild.getLeft()>=(mMenuWidth/2)){
                    open();
                }else{
                    close();
                }
            }
        }


以上方法是用来处理当view滑动停止的会被调用 在这个方法里 主要用来处理view的 滑动

view的滑动可以使用ViewDragHelper中的smoothSlideViewTo方法 当然还有一些特效比如透明的方法都是有的

这就看出啦VeewDragHelper类是多么的强大

private void open(){
        mState =STATE.open;
        mDragHelper.smoothSlideViewTo(childView, mMenuWidth, 0);
        computeScroll();
    }
    private void close(){
        mState =STATE.close;
        mDragHelper.smoothSlideViewTo(childView, 0, 0);
        computeScroll();
    }

以上是自己定义的两个处理打开很关闭的方法 用的就是smoothSlideViewTo

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

ViewCompat.postInvalidateOnAnimation(this); 方法用来实现动画效果 源码中会调用Scroller来实现 有兴趣的同学可以自己看一下

而在此之前 我们还有一个步骤要做  那就是要处理onTouchEVent 和 onInterceptTouchEvent 

public boolean onTouchEvent(MotionEvent event) {
        
       
        mDragHelper.processTouchEvent(event);
        return true;
    }


    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        return mDragHelper.shouldInterceptTouchEvent(ev);
    }

我们需要在这两个方法中对ViewDragHelper的事件进行注册 如果我们还需要在onTouchEvent中处理up 和down事件 一定要把注册事件放在最前面 优先处理

下载地址:

http://download.csdn.net/detail/haoxuezhe1988/8811991


发布了56 篇原创文章 · 获赞 3 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/haoxuezhe1988/article/details/46517421