Recyclerview橫向滾動條,仿淘寶快捷入口

直接上圖吧

1.RecyclerViewScrollBar類

public class RecyclerViewScrollBar extends View {

    private RecyclerView mRecyclerView;

    private int mWidth;

    private int mHeight;

    private Drawable mTrackHorizontal;

    private Drawable mThumbHorizontal;

    private Rect mTrackRect = new Rect();

    private Rect mThumbRect = new Rect();

    private float mThumbScale = 0.00F;

    private float mScrollScale = 0.00F;

    private final int SCROLL_LOCATION_START = 1;

    private final int SCROLL_LOCATION_END = 2;

    private final int SCROLL_LOCATION_SCROLL = 3;

    float mScrollRange = 0.00f;

    float mScrollOffset = 0.00f;

    float mScrollExtent = 0.00f;


    /**
     * View的當前位置,起點 終點 或滾動中
     */
    private int mScrollLocation = SCROLL_LOCATION_START;

    private final RecyclerView.OnScrollListener mScrollListener =
            new RecyclerView.OnScrollListener() {

                @Override
                public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
                    super.onScrollStateChanged(recyclerView, newState);
                    computeScrollScale();
                }

                @Override
                public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                    super.onScrolled(recyclerView, dx, dy);
                    computeScrollScale();
                    postInvalidate();
                }
            };


    public RecyclerViewScrollBar(Context context) {
        this(context, null);
    }

    public RecyclerViewScrollBar(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    @SuppressLint("Recycle")
    public RecyclerViewScrollBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        final TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.RecyclerViewScrollBar);
        mTrackHorizontal = array.getDrawable(R.styleable.RecyclerViewScrollBar_scrollbarTrackHorizontal);
        mThumbHorizontal = array.getDrawable(R.styleable.RecyclerViewScrollBar_scrollbarThumbHorizontal);
    }

    public void bindRecyclerView(@Nullable RecyclerView recyclerView) {
        if (mRecyclerView == recyclerView) {
            return;
        }
        mRecyclerView = recyclerView;
        if (mRecyclerView != null) {
            setupCallbacks();
        }
    }

    private void setupCallbacks() {
        mRecyclerView.addOnScrollListener(mScrollListener);
        //監聽View的視圖樹變化,防止初始化未獲取到滾動條比例
        mRecyclerView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                computeScrollScale();
            }
        });
        computeScrollScale();
    }

    public void computeScrollScale() {
        if (mRecyclerView == null) return;
        //RecyclerView已顯示寬度
        mScrollExtent = mRecyclerView.computeHorizontalScrollExtent();
        //RecyclerView實際寬度
        mScrollRange = mRecyclerView.computeHorizontalScrollRange();
        if (mScrollRange != 0 && mScrollExtent != 0) {
            mThumbScale = mScrollExtent / mScrollRange;
        }
        //RecyclerView已經滾動的距離
        mScrollOffset = mRecyclerView.computeHorizontalScrollOffset();
        if (mScrollOffset != 0 && mScrollRange != 0) {
            mScrollScale = mScrollOffset / mScrollRange;
        }
        //RecyclerView可以滾動的距離
        float mCanScrollDistance = mScrollRange - mScrollExtent;
        if (mScrollOffset == 0) {
            mScrollLocation = SCROLL_LOCATION_START;
        } else if (mCanScrollDistance == mScrollOffset) {
            mScrollLocation = SCROLL_LOCATION_END;
        } else {
            mScrollLocation = SCROLL_LOCATION_SCROLL;
        }
        postInvalidate();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        mWidth = measureHandler(widthMeasureSpec);
        mHeight = measureHandler(heightMeasureSpec);
        setMeasuredDimension(mWidth, mHeight);
    }

    private int measureHandler(int measureSpec) {
        int result = 0;
        int size = MeasureSpec.getSize(measureSpec);
        int mode = MeasureSpec.getMode(measureSpec);
        if (mode == MeasureSpec.EXACTLY) {
            result = size;
        } else if (mode == MeasureSpec.AT_MOST) {
            result = Math.max(size, result);
        }
        return result;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (mTrackHorizontal != null) {
            mTrackRect.set(0, 0, mWidth, mHeight);
            mTrackHorizontal.setBounds(mTrackRect);
            mTrackHorizontal.draw(canvas);
        }
        int wid = (mWidth * 2) / 5;
        //left座標
        int mThumbLeft = (int)((mScrollOffset * (mWidth - wid) ) / (mScrollRange - mScrollExtent));
//        int mThumbLeft = (int) ((mScrollOffset * mWidth) * (mWidth / mScrollRange));
        //right座標
//        int mThumbRight = (int) (mThumbLeft + mWidth * mThumbScale);
        int mThumbRight = mThumbLeft + wid;

        //添加狀態是爲了修復滾動差距
        if (mThumbHorizontal != null) {
//            switch (mScrollLocation) {
//                case SCROLL_LOCATION_START:
//                    mThumbRect.set(0, 0, mThumbRight, mHeight);
//                    break;
//                case SCROLL_LOCATION_SCROLL:
//
//                    break;
//                case SCROLL_LOCATION_END:
//                    mThumbRect.set(mThumbLeft, 0, mWidth, mHeight);
//                    break;
//            }
            mThumbRect.set(mThumbLeft, 0, mThumbRight, mHeight);
            mThumbHorizontal.setBounds(mThumbRect);
            mThumbHorizontal.draw(canvas);
        }
    }
}

主要就是熟悉RecyclerView的長度方法計算

//RecyclerView已顯示寬度
mScrollExtent = mRecyclerView.computeHorizontalScrollExtent();
//RecyclerView實際寬度
mScrollRange = mRecyclerView.computeHorizontalScrollRange();
if (mScrollRange != 0 && mScrollExtent != 0) {
    mThumbScale = mScrollExtent / mScrollRange;
}
//RecyclerView已經滾動的距離
mScrollOffset = mRecyclerView.computeHorizontalScrollOffset();

 

2.MainActivity

public class MainActivity extends AppCompatActivity {

    @BindView(R.id.recyclerView)
    RecyclerView recyclerView;

    @BindView(R.id.recycler_view_bar)
    RecyclerViewScrollBar recyclerViewBar;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        ButterKnife.bind(this);

        initView();

    }

    private void initView(){
        recyclerView.setLayoutManager(new StaggeredGridLayoutManager
                (2, StaggeredGridLayoutManager.HORIZONTAL));
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        recyclerView.setNestedScrollingEnabled(false);

        recyclerViewBar.bindRecyclerView(recyclerView);

        ItemAdapter itemAdapter = new ItemAdapter(this);
        recyclerView.setAdapter(itemAdapter);

        List<String> stringList = new ArrayList<>();

        for(int i=0; i<20; i++){
            stringList.add(i + "");
        }

        itemAdapter.replaceData(stringList);
    }



}

很簡單的實現,直接可以拿到項目裏去用。

源碼地址:https://download.csdn.net/download/u010090644/12291254

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章