当RecyclerView item高度不同时,如何固定scrollbar的高度

当RecyclerView item高度不同时,如何固定scrollbar的高度

The best way to handle this situation may be to somehow calculate the scroll bar range based on the size of each item. That may not be practical or desirable. In lieu of that, here is a simple implementation of a custom RecyclerView that you can play with to try to get what you want. It will show you how you can use the various scroll methods to control the scroll bar. It will stick the size of the thumb to an initial size based upon the number of items displayed. The key thing to remember is that the scroll range is arbitrary but all other measurements (extent, offset) must use the same units.

 https://stackoverflow.com/questions/46033473/recyclerview-with-items-of-different-height-scrollbar

如何

public class MyRecyclerView extends RecyclerView {
    // The size of the scroll bar thumb in our units.
    private int mThumbHeight = UNDEFINED;

    // Where the RecyclerView cuts off the views when the RecyclerView is scrolled to top.
    // For example, if 1/4 of the view at position 9 is displayed at the bottom of the RecyclerView,
    // mTopCutOff will equal 9.25. This value is used to compute the scroll offset.
    private float mTopCutoff = UNDEFINED;

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

    public MyRecyclerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public MyRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    /**
     * Retrieves the size of the scroll bar thumb in our arbitrary units.
     *
     * @return Scroll bar thumb height
     */
    @Override
    public int computeVerticalScrollExtent() {
        return (mThumbHeight == UNDEFINED) ? 0 : mThumbHeight;
    }

    /**
     * Compute the offset of the scroll bar thumb in our scroll bar range.
     *
     * @return Offset in scroll bar range.
     */
    @Override
    public int computeVerticalScrollOffset() {
        return (mTopCutoff == UNDEFINED) ? 0 : (int) ((getCutoff() - mTopCutoff) * ITEM_HEIGHT);
    }

    /**
     * Computes the scroll bar range. It will simply be the number of items in the adapter
     * multiplied by the given item height. The scroll extent size is also computed since it
     * will not vary. Note: The RecyclerView must be positioned at the top or this method
     * will throw an IllegalStateException.
     *
     * @return The scroll bar range
     */
    @Override
    public int computeVerticalScrollRange() {
        if (mThumbHeight == UNDEFINED) {
            LinearLayoutManager lm = (LinearLayoutManager) getLayoutManager();
            int firstCompletePositionw = lm.findFirstCompletelyVisibleItemPosition();

            if (firstCompletePositionw != RecyclerView.NO_POSITION) {
                if (firstCompletePositionw != 0) {
                    throw (new IllegalStateException(ERROR_NOT_AT_TOP_OF_RANGE));
                } else {
                    mTopCutoff = getCutoff();
                    mThumbHeight = (int) (mTopCutoff * ITEM_HEIGHT);
                }
            }
        }
        return getAdapter().getItemCount() * ITEM_HEIGHT;
    }

    /**
     * Determine where the RecyclerVIew display cuts off the list of views. The range is
     * zero through (getAdapter().getItemCount() - 1) inclusive.
     *
     * @return The position in the RecyclerView where the displayed views are cut off. If the
     * bottom view is partially displayed, this will be a fractional number.
     */
    private float getCutoff() {
        LinearLayoutManager lm = (LinearLayoutManager) getLayoutManager();
        int lastVisibleItemPosition = lm.findLastVisibleItemPosition();

        if (lastVisibleItemPosition == RecyclerView.NO_POSITION) {
            return 0f;
        }

        View view = lm.findViewByPosition(lastVisibleItemPosition);
        float fractionOfView;

        if (view.getBottom() < getHeight()) { // last visible position is fully visible
            fractionOfView = 0f;
        } else { // last view is cut off and partially displayed
            fractionOfView = (float) (getHeight() - view.getTop()) / (float) view.getHeight();
        }
        return lastVisibleItemPosition + fractionOfView;
    }

    private static final int ITEM_HEIGHT = 1000; // Arbitrary, make largish for smoother scrolling
    private static final int UNDEFINED = -1;
    private static final String ERROR_NOT_AT_TOP_OF_RANGE
            = "RecyclerView must be positioned at the top of its range.";
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值