自定义一个LinearLayoutManager

这个是给我自己看的熟悉LayoutManager文中注释很清楚了

public class CustomLayoutManager extends RecyclerView.LayoutManager {


    @Override
    public RecyclerView.LayoutParams generateDefaultLayoutParams() {
        return new RecyclerView.LayoutParams(RecyclerView.LayoutParams.WRAP_CONTENT, RecyclerView.LayoutParams.WRAP_CONTENT);
    }

    //用来存取每一个itemView的位置信息
    private SparseArray<Rect> itemRects = null;
    private int mTotalHeight = -1;//总的itemView的总高度
    private boolean oneFlag = true;//看是否是第一次加载
    private int mTheMoveDistance = 0;//实际的位移

    /**
     * 判断是符合条件
     *
     * @param state
     * @return
     */
    private boolean cut(RecyclerView.State state) {
        if (oneFlag) {
            oneFlag = false;
            return true;
        }

        if (getItemCount() <= 0 || state.isPreLayout()) {
            return true;
        }
        return false;
    }

    @Override
    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
        super.onLayoutChildren(recycler, state);
        if (cut(state)) return;
        detachAndScrapAttachedViews(recycler);
        //1.获取一个item高度
        int itemHeight = initStepHeight(recycler);
        //2.获取可见高度的中总的item数,也就是getchildCount()
        int visibleCount = initVisibleCounts(itemHeight);
        //3.计算每个item的位置信息
        initItemRectSparse(itemHeight);
        //4把可见的item放在现实出来
        layoutChilder(recycler, visibleCount);

    }

    //获取可见高度
    public int getVerticalVisibleHeight() {
        return getHeight() - getPaddingTop() - getPaddingBottom();
    }


    //计算可见区域的rect
    public Rect getVisiblArea() {
        return new Rect(getPaddingLeft(),
                getPaddingTop() + mTheMoveDistance,
                getWidth() + getPaddingRight(),
                getVerticalVisibleHeight() + mTheMoveDistance);
    }

    //计算一个item的高度这里是高度不变的情况
    public int initStepHeight(RecyclerView.Recycler recycler) {
        View childView = recycler.getViewForPosition(0);
        addView(childView);
        measureChildWithMargins(childView, 0, 0);
        int result = getDecoratedMeasuredHeight(childView);
        removeAndRecycleAllViews(recycler);
        return result;
    }


    //计算可见区域item的个数
    public int initVisibleCounts(int steHeight) {
        return getVerticalVisibleHeight() / steHeight;
    }

    /**
     * 计算每个条目位置信息
     *
     * @param stepItemHeight 一个item的高度
     */
    public void initItemRectSparse(int stepItemHeight) {
        itemRects = new SparseArray<>();
        int offfsetY = getPaddingTop();
        for (int i = 0; i < getItemCount(); i++) {
            itemRects.put(i, new Rect(getPaddingLeft(), offfsetY, getWidth() + getPaddingRight(), offfsetY + stepItemHeight));
            offfsetY += stepItemHeight;
            mTotalHeight = offfsetY;
        }
    }

    //显示可见item
    public void layoutChilder(RecyclerView.Recycler recycler, int visibleCount) {
        detachAndScrapAttachedViews(recycler);
        for (int i = 0; i < visibleCount; i++) {
            View childView = recycler.getViewForPosition(i);
            addView(childView);
            measureChildWithMargins(childView, 0, 0);
            layoutDecorated(childView, itemRects.get(i).left, itemRects.get(i).top, itemRects.get(i).right, itemRects.get(i).bottom);
        }
    }

    @Override
    public boolean canScrollVertically() {
        return true;
    }

    @Override
    public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {
        dy = handleScroll(dy, recycler, state);
        handleRecycle(recycler,state);
        return dy;
    }


    public int handleScroll(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {

        //获取可见高度
        int theRvVisibleHeight = getVerticalVisibleHeight();
        //获取不可见的总高度
        int theMoreHeight = mTotalHeight - theRvVisibleHeight;
        if (mTheMoveDistance + dy < 0) {//到达顶点
            //修复边界
            dy = -mTheMoveDistance;
        } else if (mTotalHeight > theRvVisibleHeight && mTheMoveDistance + dy > theMoreHeight) {
            dy = theMoreHeight - mTheMoveDistance;
        }
        mTheMoveDistance += dy;
        offsetChildrenVertical(-dy);
        return dy;
    }

    //处理回收问题
    private void handleRecycle(RecyclerView.Recycler recycler, RecyclerView.State state) {
        if (cut(state))return;
        detachAndScrapAttachedViews(recycler);
        //1获取可见区域的rect
        Rect visiblArea = getVisiblArea();
        //2获取已经存取过的所有item位置信息的itemRect
        for (int i = 0; i < getItemCount(); i++) {
            View childView = recycler.getViewForPosition(i);
            //比较当前view是否在可见区域 不在回收在显示
            Rect rect = itemRects.get(i);
            if (Rect.intersects(visiblArea,rect)){
                addView(childView);
                measureChildWithMargins(childView,0,0);
                //让不见变为可见就要减掉当前的位移也就是 mTheMoveDistance 否则显示不出来
                layoutDecorated(childView,rect.left,rect.top-mTheMoveDistance,rect.right,rect.bottom-mTheMoveDistance);
            }else{//不可见回收
                removeAndRecycleView(childView,recycler);
            }
        }
    }

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值