美文网首页
ViewDragHelper学习及使用

ViewDragHelper学习及使用

作者: 彡Panda彡 | 来源:发表于2019-03-24 22:39 被阅读0次

    工作中需要开发一个类似于抽屉式的滑动的 View,同过调研及查找资料发现ViewDragHelper可以实现此类方式,在此记录下ViewDragHelper的学习及使用。

    首先 ViewDragHelper 分为三部:

    1. 创建 ViewDragHelper 实例,通过
      ViewDragHelper.create(ViewGroup forParent, float sensitivity, Callback cb)
      创建ViewDragHelper实例,其中:
      ViewGroup:当前的ViewGroup
      sensitivity:设置滑动灵敏度,通常为 1
      cb:拖拽回调,用来处理拖动位置相关回调
    2. 实现 ViewDragHelper.Callback() 相关方法:
    mViewDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
                @Override
                public boolean tryCaptureView(@NonNull View child, int pointerId) {
                    return false;
                }
    
    
                @Override
                public int clampViewPositionVertical(@NonNull View child, int top, int dy) {
                    return super.clampViewPositionVertical(child, top, dy);
                }
                
                @Override
                public int clampViewPositionHorizontal(@NonNull View child, int left, int dx) {
                    return super.clampViewPositionHorizontal(child, left, dx);
                }
        }
    

    该回调可以移动相关的处理,比如哪些 view 可以移动,以及移动的边界处理等。其中参数如下:

    • tryCaptureView: 返回 true 表示捕获相关 View,根据传入的 child 确定要捕获的 view
    • clampViewPositionVertical(View child, int top, int dy)clampViewPositionHorizontal(View child, int left, int dx): child 移动边界控制,其中 top,left 表示移动到的位置。
    1. 处理 ViewGroup 的触摸事件
    @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            return mViewDragHelper.shouldInterceptTouchEvent(ev);
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            mViewDragHelper.processTouchEvent(event);
            return true;
        }
    

    onInterceptTouchEvent:交给 mViewDragHelper.shouldInterceptTouchEvent(ev) 进行处理

    onTouchEvent:交给 mViewDragHelper.processTouchEvent(event) 进行处理

    简单的使用就如上所示,当如,其中如果进行复杂的处理,还需更多的用法,比如:

    • 边界触摸检测
    • 拖拽释放回调
    • 移动到某个指定位置

    比如如下重写的方法:

    mViewDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
                @Override
                public boolean tryCaptureView(@NonNull View child, int pointerId) {
                    return child == mDragView;
                }
    
    
                @Override
                public int clampViewPositionVertical(@NonNull View child, int top, int dy) {
                    if (top > getHeight() - mDragViewHight) {
                        top = getHeight() - mDragViewHight;
                    } else if (top < MIN_TOP) {
                        top = MIN_TOP;
                    }
                    return top;
                }
    
                @Override
                public int getViewVerticalDragRange(@NonNull View child) {
                    return getMeasuredHeight() - child.getMeasuredHeight();
                }
    
                @Override
                public void onViewPositionChanged(@NonNull View changedView, int left, int top, int dx, int dy) {
                    super.onViewPositionChanged(changedView, left, top, dx, dy);
    
                    LinearLayout.LayoutParams bottomViewLayoutPara = (LayoutParams) mBottomView.getLayoutParams();
                    bottomViewLayoutPara.height = bottomViewLayoutPara.height + dy * -1;
                    mBottomView.setLayoutParams(bottomViewLayoutPara);
    
                    LinearLayout.LayoutParams topViewLayoutPara = (LayoutParams) mTopView.getLayoutParams();
                    topViewLayoutPara.height = topViewLayoutPara.height + dy;
                    mTopView.setLayoutParams(topViewLayoutPara);
                }
            });
        }
    

    其中:

    • getViewVerticalDragRange 返回child 垂直移动范围的距离,如果不加,当有点击事件之后则不触发
    • onViewPositionChanged 当位置改变进行回调

    同时除了以上方法之外还有其余如下方法:

    • onViewDragStateChanged:ViewDragHelper状态改变时进行回调(IDLE,DRAGGING,SETTING)
    • onEdgeTouched:触摸到边界是回调
    • onEdgeDragStarted:边界拖动时回调,需设置 setEdgeTrackingEnabled() ,可以设置如下
      • EDGE_LEFT:左边界
      • EDGE_TOP:上边界
      • EDGE_RIGHT:右边界
      • EDGE_BOTTOM:底部边界
        附实现效果:


        效果图

        附代码(DragView):

    public class DragView extends LinearLayout {
    
        private View mTopView;
        private View mDragView;
        private View mBottomView;
    
        private ViewDragHelper mViewDragHelper;
    
        private int mDragViewHight;
    
        final int MIN_TOP = 100;
    
    
        public DragView(Context context) {
            super(context);
            init();
        }
    
        public DragView(Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
            init();
        }
    
        public DragView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }
    
        private void init() {
            mViewDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
                @Override
                public boolean tryCaptureView(@NonNull View child, int pointerId) {
                    return child == mDragView;
                }
    
    
                @Override
                public int clampViewPositionVertical(@NonNull View child, int top, int dy) {
                    if (top > getHeight() - mDragViewHight) {
                        top = getHeight() - mDragViewHight;
                    } else if (top < MIN_TOP) {
                        top = MIN_TOP;
                    }
                    return top;
                }
    
                @Override
                public int getViewVerticalDragRange(@NonNull View child) {
                    return getMeasuredHeight() - child.getMeasuredHeight();
                }
    
                @Override
                public void onViewPositionChanged(@NonNull View changedView, int left, int top, int dx, int dy) {
                    super.onViewPositionChanged(changedView, left, top, dx, dy);
    
                    LinearLayout.LayoutParams bottomViewLayoutPara = (LayoutParams) mBottomView.getLayoutParams();
                    bottomViewLayoutPara.height = bottomViewLayoutPara.height + dy * -1;
                    mBottomView.setLayoutParams(bottomViewLayoutPara);
    
                    LinearLayout.LayoutParams topViewLayoutPara = (LayoutParams) mTopView.getLayoutParams();
                    topViewLayoutPara.height = topViewLayoutPara.height + dy;
                    mTopView.setLayoutParams(topViewLayoutPara);
                }
            });
        }
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            return mViewDragHelper.shouldInterceptTouchEvent(ev);
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            mViewDragHelper.processTouchEvent(event);
            return true;
        }
    
        @Override
        protected void onFinishInflate() {
            super.onFinishInflate();
            mTopView = getChildAt(0);
            mDragView = getChildAt(1);
            mBottomView = getChildAt(2);
        }
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            mDragViewHight = mDragView.getMeasuredHeight();
        }
    }
    

    相关文章

      网友评论

          本文标题:ViewDragHelper学习及使用

          本文链接:https://www.haomeiwen.com/subject/xyopvqtx.html