一个Manager轻松让RecycleView指定item项置顶

RecycleView指定item项置顶效果


在这里插入图片描述
由于最近需求需 当滑过列表中的某一项时置顶该item项,网上也搜索了下 大多是通过ItemDecoration 来实现 原理是获指定item的view视图通过分割线去来来绘制出来.但是我的置顶item是一个横向的recycleview 能滑动能点击.而通过分割线的方式只能有点击事件.所以此种方式不适用于我的情况

所以采用滚动监听事件来失效此效果

根据判断第一项可见的position来做逻辑

如果第一项可见的item的位置小于指定item的话隐藏掉置顶布局
其他情况显示置顶布局
采用自定义LayoutManager的方式来实现

package cn.lhj.stickhead;

import android.content.Context;
import android.os.Build;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.View;

/**
 * Filedescription.
 * 指定item项吸顶
 * @author lihongjun
 * @date 2018/10/8
 */
public class StickLayoutManager extends LinearLayoutManager{

    private int mStickPosition = -1; // 吸顶position
    private View mStickView; // 吸顶布局

    public StickLayoutManager(Context context) {
        super(context);
    }

    public StickLayoutManager(Context context, int orientation, boolean reverseLayout) {
        super(context, orientation, reverseLayout);
    }

    public StickLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    /**
     * 设置吸顶的position
     *
     * @param stickPosition
     */
    public void setStickPosition(int stickPosition) {
        mStickPosition = stickPosition;
    }

    /**
     * 设置吸顶的布局
     *
     * @param stickView
     */
    public void setStickView(View stickView) {
        setStickView(stickView,0);
    }

    /**
     * 设置吸顶的布局
     *
     * @param stickView
     * @param elevation 阴影值 dp
     */
    public void setStickView(View stickView,int elevation) {
        mStickView = stickView;
        if (stickView != null && elevation > 0) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                if (mStickView.getTag() != null) {
                    // 已经设置过阴影了
                    return;
                }
                mStickView.setTag(true);
                mStickView.animate().z(elevation);
            }
        }
    }

    @Override
    public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {
        int scroll = super.scrollVerticallyBy(dy, recycler, state);
        if (Math.abs(scroll) > 0) {
            if (mStickPosition == -1) { // 如果列表中不存在二级分则返回
                hideStickView();
                return scroll;
            }
            changeFirstVisibilityStatu();
        }
        return scroll;
    }

    /**
     * 根据位置变化检测吸顶布局的显示状态
     */
    private void changeFirstVisibilityStatu() {
        if (findFirstVisibleItemPosition() < mStickPosition) {
            hideStickView();
        } else if (findFirstVisibleItemPosition() == mStickPosition) {
            View view = findViewByPosition(mStickPosition);
            if (view != null && view.getTop() < 0) {
                showStickView();
            } else {
                hideStickView();
            }
        } else {
            showStickView();
        }
    }

    /**
     * 隐藏吸顶布局
     */
    private void hideStickView() {
        if (mStickView != null && mStickView.getVisibility() != View.GONE) {
            mStickView.post(new Runnable() { // 如果父布局是ConstraintLayout会导致吸顶布局状态不对 用主线程队列去更新状态
                @Override
                public void run() {
                    mStickView.setVisibility(View.GONE);
                }
            });
        }
    }

    /**
     * 显示吸顶布局
     */
    private void showStickView() {
        if (mStickView != null && mStickView.getVisibility() != View.VISIBLE) {
            mStickView.post(new Runnable() {// 如果父布局是ConstraintLayout会导致吸顶布局状态不对 用主线程队列去更新状态
                @Override
                public void run() {
                    mStickView.setVisibility(View.VISIBLE);
                }
            });
        }
    }

    @Override
    public void onLayoutCompleted(RecyclerView.State state) {
        super.onLayoutCompleted(state);
        changeFirstVisibilityStatu();
    }
}

遇到的坑就
1.通过调用RecycleView的scrollToPosition,置顶布局不能正常的显示出来,发现是因为scrollToPosition会使recycleView requestLayout,然后会super.requestLayout;现在采用sitckView.post来避免此问题
2.通过调用recycleView的scrollToPosition方式不会出发scroll回掉
需要在onLayoutCompleted回掉中监测可见的第一项来确定吸顶布局的显示状态

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值