手写RecyclerView和RecylerView回收池-3

自定义RecyclerView滑动

  • 拦截事件处理,自定义View自己处理滑动
  • 向上滑动&&向下滑动
  • 滑动偏差处理

拦截事件处理,自定义View自己处理滑动

  • 坐标示例图


    151519472162825.png
  • onInterceptTouchEvent方法处理
 /**
     * 重写onInterceptTouchEvent方法,来决定滑动还是不滑动
     * @param ev
     * @return
     */
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        boolean intercept=false;
        switch (ev.getAction()){
            case MotionEvent.ACTION_DOWN:
                currentY=(int)ev.getRawY();
                break;
            case MotionEvent.ACTION_MOVE:
                //取出手指当前移动到的Y轴值,跟之前记录的手指触摸位置y相减求差值。
                float y2=Math.abs(currentY-ev.getRawY());
                //分两种情况
                /**
                 * 1、小于最小滑动距离 就不滑动
                 * 2、如果大于最小滑动距离 就滑动
                 */
                if(y2>touchSlop){
                    intercept=true;
                }
                break;
        }
        return intercept;
    }
  • 处理滑动
   @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_MOVE:
                //先获取到当前Y轴的值
                float y2=event.getRawY();
                //手指触摸减去滑动到的这个Y轴的值
                float diff=currentY-y2;
                //不加会影响反应速度
                currentY=(int)y2;
                //调用滑动方法
                scrollBy(0,(int)diff);
                break;
        }
        return super.onTouchEvent(event);
    }

向上滑动&&向下滑动

  • 上下滑动
  @Override
    public void scrollBy(int x, int y) {
        scrollY+=y;
        //处理滑动边界问题,纠正scrollY
//        scrollY=scrollBounds(scrollY);
        if(scrollY>0){//向上滑
            /**
             * 上滑需要做两件事情
             * 1、将屏幕上方的ItemView移除
             * 2、给屏幕下方添加一个新的ItemView进来
             */
            //1、将屏幕上方的ItemView移除
            while (scrollY>heights[firstRow]){
                //删除第一行,就是删除当前布局中的第0个Item
                removeView(viewlist.remove(0));
                //改变scrolly 要减去这一行的高度
                scrollY-=heights[firstRow];
                //当前显示的行标
                firstRow++;
            }
            //2、给屏幕下方添加一个新的ItemView进来
            //判断当前所显示的View的高度是不是小于RecylerView的高度,如果小于,就添加新的Item
            while (getFillHeight()=height){
                //移除当前显示的在最下面的ItemView
                removeView(viewlist.remove(viewlist.size()-1));
            }

        }else{

        }
        //重新摆放位置
        rePositionView();
    }

   /**
     * 获取到显示在控件中View的总高度
     * @return
     */
    private int getFillHeight() {
        return sumArray(heights,firstRow,viewlist.size())-scrollY;

    }

  • 重新摆放位置
  /**
     * 当我们上拉或者下滑的时候,重新摆放View的位置
     */
    private void rePositionView() {
        int top=0,right,bottom,left=0,i;
        top-=scrollY;
        //将当前第一行的行标赋值给i
        i=firstRow;
        for (View view:viewlist){
            //重新摆放View
            bottom=top+heights[i++];
            view.layout(0,top,width,bottom);
            top=bottom;
        }


    }

滑动偏差处理

  • 运行看结果


    微信截图_20221130101156.png
  • 纠正scrolly值
   /**
     * 纠正scrollY值
     * @param scrollY
     * @return
     */
    private int scrollBounds(int scrollY) {
        if(scrollY>0){
            //判断上滑的极限  防止滚动的距离  大于当前所有内容的高度
            scrollY=Math.min(scrollY,sumArray(heights,firstRow,heights.length-firstRow)-height);
        }else{
            //判断下滑的极限值,防止滚动的距离 小于第0个Item的高度
            scrollY=Math.max(scrollY,-sumArray(heights,0,firstRow));
        }
        return scrollY;
    }
  • 运行效果(可以正常滑动)


    image.png

好的,我们这节课就到这里,我们下节课讲RecyclerView回收池,再见

你可能感兴趣的:(手写RecyclerView和RecylerView回收池-3)