美文网首页
自定义View-26 仿二手车之家折叠列表

自定义View-26 仿二手车之家折叠列表

作者: zsj1225 | 来源:发表于2018-07-14 18:17 被阅读123次

    模仿效果如下:


    Gif_20180714_161036.gif

    1、效果分析

    1、前面列表可以动,后面菜单不可以动
    2、 只能垂直滑动
    3、 垂直滑动的距离只能是后面菜单的高度
    4、 手指松开二选一,要么打开菜单,要么关闭菜单

    2、代码实现

    2.1、前面列表可以动,后面菜单不可以动

        @Override
        protected void onFinishInflate() {
            super.onFinishInflate();
    
            int childCount = getChildCount();
            if (childCount != 2){
                throw new RuntimeException("VerticalDragListView 只能有两个子View");
            }
    
            //列表
            mDragList = getChildAt(1);
        }
    
        ViewDragHelper.Callback mDragCallback = new ViewDragHelper.Callback() {
            @Override
            public boolean tryCaptureView(@NonNull View child, int pointerId) {
                //2,1 前面列表可以动,后面菜单不可以动
                return mDragList == child;
            }
    }
    

    2.2、只能垂直滑动

        ViewDragHelper.Callback mDragCallback = new ViewDragHelper.Callback() {
            @Override
            public int clampViewPositionVertical(@NonNull View child, int top, int dy) {
                // 2.2 只能垂直滑动
                return top;
            }
        };
    

    2.3、垂直滑动的距离只能是后面菜单的高度

        @Override
        protected void onFinishInflate() {
            super.onFinishInflate();
            //获取后面的菜单
            mMenuView = getChildAt(0);
        }
    
        @Override
        protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
            super.onLayout(changed, left, top, right, bottom);
            if (changed) {
                //2.3.1 获取菜单的高度 ,只要在setMeasuredDimension后面都可以拿到控件的宽高
                mMenuHeight = mMenuView.getMeasuredHeight();
            }
        }
    
        ViewDragHelper.Callback mDragCallback = new ViewDragHelper.Callback() {
            @Override
            public int clampViewPositionVertical(@NonNull View child, int top, int dy) {
                // 2.3、垂直滑动的距离只能是后面菜单的高度
                // 2.3.1、先获取后面菜单的高度
                if (top < 0) {
                    top = 0;
                }
                if (top> mMenuHeight){
                    top = mMenuHeight;
                }
                return top;
            }
    }
    

    2.4、 手指松开二选一,要么打开菜单,要么关闭菜单

        ViewDragHelper.Callback mDragCallback = new ViewDragHelper.Callback() {
            @Override
            public void onViewReleased(@NonNull View releasedChild, float xvel, float yvel) {
                if (releasedChild == mDragList) {
                    // 2.4、 手指松开二选一,要么打开菜单,要么关闭菜单
                    if (mDragList.getTop() > mMenuHeight / 2) {
                        // 2.4.1 当 滑动的距离大于菜单高度的一半,打开菜单
                        mViewDragHelper.settleCapturedViewAt(0, mMenuHeight);
                    } else {
                        //否则,关闭菜单
                        mViewDragHelper.settleCapturedViewAt(0, 0);
                    }
                    invalidate();
                }
            }
        };
    
        @Override
        public void computeScroll() {
            if (mViewDragHelper.continueSettling(true)) {
                invalidate();
            }
        }
    

    3、处理事件拦截

    
        /**
         * 事件拦截
         */
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            //3 处理事件拦截
            // 3.2 当菜单打开的时候。执行自己的onTouchEvent方法
            if (mMenuIsOpen) {
                return true;
            }
    
            switch (ev.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    mDownY = ev.getY();
                    //gnoring pointerId=0 because ACTION_DOWN was not received for this pointer before ACTION_MOVE
                    //让mViewDragHelper有ACTION_DOWN的完整流程
                    mViewDragHelper.processTouchEvent(ev);
                    break;
    
                case MotionEvent.ACTION_MOVE:
                    // 3.1 当向下滑动 && 列表在最顶部的时候 拦截事件,return true 。走自己的onTouchEvent方法
                    float moveY = ev.getY();
                    if (moveY > mDownY && !canChildScrollUp()) {
                        return true;
                    }
                    break;
    
                default:
                    break;
            }
    
            return super.onInterceptTouchEvent(ev);
        }
    
    
        /**
         * 还能不能向上滑动,如果可以返回true,否则返回false
         *
         * @return Whether it is possible for the child view of this layout to
         * scroll up. Override this if the child view is a custom view.
         */
        public boolean canChildScrollUp() {
            if (mDragList instanceof ListView) {
                return ListViewCompat.canScrollList((ListView) mDragList, -1);
            }
            return mDragList.canScrollVertically(-1);
        }
    

    4、效果

    Gif_20180714_182049.gif

    5、完整代码

    verticaldraglistview

    相关文章

      网友评论

          本文标题:自定义View-26 仿二手车之家折叠列表

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