自定义View折叠列表

在这里做了一个折叠列表的效果,先看下效果图
Gif_20180418_214031.gif

在这个效果这里我用的是ViewDragHelper来做的。先写一个类继承自FramLayout。在这个类的构造函数里创建出ViewDragHelper。

viewDragHelper = ViewDragHelper.create(this, mViewDragHelperCallBack);

在这里ViewDragHelper不能new出来,要去调用它的create方法,是因为它的构造函数私有化了。在它的两个参数里一个是当前的类也就是布局本身,类外一个要传入一个CallBack。在这个CallBack里面有可以让内部子view可以移动的方法。

  private ViewDragHelper.Callback mViewDragHelperCallBack = new ViewDragHelper.Callback() {
     @Override
     public boolean tryCaptureView(View child, int pointerId) {
         //表示能能让前面的那个view滑动
         return mListView == child;
     }

     @Override
     public int clampViewPositionVertical(View child, int top, int dy) {
         //控制前面的view滑动的范围
         if (top<=0){
             top=0;
         }
         if (top>= measuredHeight){
             top = measuredHeight;
         }
         return top;
     }
     //在手指松开的时候,选择打开还是关闭
        @Override
        public void onViewReleased(View releasedChild, float xvel, float yvel) {
            super.onViewReleased(releasedChild, xvel, yvel);
            if (releasedChild == mListView){
                if (mListView.getTop()>measuredHeight/2){
                    // 滚动到菜单的高度(打开)
                    viewDragHelper.settleCapturedViewAt(0,measuredHeight);
                    mMenuIsOpen = true;
                }else {
                    mMenuIsOpen = false;
                    viewDragHelper.settleCapturedViewAt(0,0);
                }

                invalidate();
            }
        }
    };

在这里我们用到了它的三个方法,第一个是表示滑动的是那个view,第二个是表示让view垂直滑动,第三个方法表示的事在滑动完之后可以让view停在那里的方法。当定义好这个自定义view之后,我们去写我们的布局




    
    



写完之后我们在我们的代码里面给listview设置数据之后,就可以看到效果了。但是这个时候滑动还是有问题的,当我们滑动到后面这个view的高度时,向上滑动listview我们会发现listview不能回到开始的位置了,那是因为在向上滑动的时候,listview的滑动事件将,我们的自定义view的事件给拦截了,所以我们在我们的自定义view的onInterceptTouchEvent里面要处理这个事件,当我们抬起手指的时候,发现我们的菜单也就是后面的view全部显示出来的时候,我们要拦截listview的事件,而去相应父view也就是我们定义的view的事件

@Override
    public boolean onInterceptTouchEvent(MotionEvent event) {


        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                //拿到按下时的y位置
                mOldY = event.getY();
                viewDragHelper.processTouchEvent(event);
                break;
            case MotionEvent.ACTION_MOVE:
                mMoveY = event.getY();
                if ((mMoveY-mOldY)>0 && !canChildScrollUp()){

                    return  true;
                }
                // 菜单打开要拦截
                if (mMenuIsOpen) {
                    return true;
                }
                break;
        }
        return super.onInterceptHoverEvent(event);
    }

我们定义了一个mMenuIsOpen来表示菜单是否打开,打开的时候我们就去返回true。
代码放到Github了
https://github.com/chenzhikaizg/MyListView

你可能感兴趣的:(自定义View折叠列表)