直接上圖吧
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