简单模仿AppbarLayout的滑动功能

2017-03-08  本文已影响278人  岁月留痕

前言

最近自己想实现一个类似AppBarLayout滑动的功能,上面一个标题栏,标题栏下面有个搜索框,在下面有个RecyclerView,滑动页面的时候标题栏固定不动搜索框随着RecyclerView上下,上去时需要滑进标题栏下面消失

实现思路

参照了DragLayout 通过Parent的layout 方法 自己动态计算两个View的位置来实现,刚好用官方的ViewDragHelper 这个类省去了很多拖动判断的代码,整个过程很简单,但是还有一些细节没有实现,这个只当巩固知识吧

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if(ev.getAction() != MotionEvent.ACTION_DOWN){
            viewDragHelper.cancel();
            return false;
        }

        viewDragHelper.shouldInterceptTouchEvent(ev);
        //这里所有的事件都拦截了,不然在RecyclerView自己拦截了后续事件,这里需要判断是否是滚动view的起始位置 或者做个接口让子类自己判断
        return true;
    }

ViewDragHelper 中主要是根据不同的view限制了滑动的top值

   ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {
        @Override
        public boolean tryCaptureView(View child, int pointerId) {
            captureView = child;
            return child == headView || child == dragContentView;
        }

        //返回拖动view垂直方向拖动的范围, 返回的是与上下的边距
        @Override
        public int clampViewPositionVertical(View child, int top, int dy) {
            //top 必须限制在刚好能隐藏headerView的位置
            int newTop = top;
            if(child == headView){
                final int minTop =  - headView.getMeasuredHeight(); //刚好将topView隐藏
                final int maxTop =  0;

                if(top <= minTop){
                    newTop = minTop;
                }else if(top >= maxTop){
                    newTop = maxTop;
                }
            }else if(child == dragContentView){ //如果是contentView那么滑动的范围刚好在顶部到 headerView的高度
                final int minTop = 0;
                final int maxTop = headView.getMeasuredHeight();
                newTop = Math.min(Math.max(top,minTop), maxTop);
            }
            return newTop;
        }

        @Override
        public void onViewReleased(View releasedChild, float xvel, float yvel) {
            super.onViewReleased(releasedChild, xvel, yvel);
            //拖动手势释放后的处理,xvel 和yvel 是速度
        }

        @Override
        public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
            super.onViewPositionChanged(changedView, left, top, dx, dy);
            //在onViewPositionChanged方法中控制拖动后新位置的处理。因为拖动过程中还需对TopView进行响应的处理,所以在方法内记录拖动的top位置
            //并在onLayout中回调处理最新位置的显示
            contentTop = top;
            requestLayout();
        }
    };

在onLayout中根据拖动的View 设置两个view的位置

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);

        //设置headView一直在ContentView头部
        if(captureView == headView || captureView == null){
            headView.layout(left,contentTop,right,contentTop+headView.getMeasuredHeight());
            dragContentView.layout(left, contentTop + headView.getMeasuredHeight(),right,bottom);
        }else {
            dragContentView.layout(left, contentTop,right,bottom);
            headView.layout(left,contentTop - headView.getHeight(),right,contentTop);

        }
    }
上一篇下一篇

猜你喜欢

热点阅读