美文网首页
简单模仿AppbarLayout的滑动功能

简单模仿AppbarLayout的滑动功能

作者: 岁月留痕 | 来源:发表于2017-03-08 19:11 被阅读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);
    
            }
        }
    

    相关文章

      网友评论

          本文标题:简单模仿AppbarLayout的滑动功能

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