時隔許久,我又要更博了,含蓄的話很少說了,今天咱們的主題是這個RecyclerView。至於爲何要加個scrollBar?由於個人業務需求是須要一個實現成這樣的,canvas
效果圖:(可能看起來比較粗糙,但功能實現了,你能夠自定義修改嘛~哈哈哈)app
可能我比較老派,個人app 中list的垂直佈局仍是喜歡用listView ,使用起來簡單(可能博主我以前有個通用的adapter不捨得放棄吧,雖然RecyclerView也有通用的adapter,但總感受顯示簡單的列表要多寫幾行代碼,有點麻煩,哈哈哈,可能我就想偷懶吧)ide
但既然今天的是這個RecyclerView那麼咱們就開始詳細的說明下吧~廢話很少說切入正題。佈局
先說下個人思路:測試
1、初始思路(想一個新玩意總得有個過程和彎路嘛),可能跟你想法同樣哦this
2、如今的實現的思路 (我想了下若是用上面的方案實現的話就,必須寫個xml文件,自定義一個ViewGroup,別人使用起來會很麻煩,固然你把他當成類庫來用也很簡單,而我就不想寫xml)spa
思路也大概說了,那麼就來看代碼的實現吧。.net
/** * @author mdm * @Description HobbyRecyclerView * @Version 1.0 */ public class HobbyRecyclerView extends RecyclerView { private RectF mRangeRectf; private Paint mRangPaint; private int showMode = 1; //滾動條寬高 private float scrollBarHeight; private float scrollBarWidth; //柱間隙 private float scrollWidthSpace ; //滾動條寬度的等分比例 private int scrollWidthWeight = 10; //Y軸的偏移值 private float yScrollOffset = 0; //全部的子view的總高度 也就是這個 private float childViewAllHeight; //可視區域的高度 其實這裏就是View高度 private float visualHeight; //可視區域的高度/全部的子view的總高度 得出的比例 float range; //recyclerView的每一個Item項的寬度 private int childWidth; //判斷觸摸焦點 private boolean isFocus = false; //手觸摸時點的x,y座標 float x = 0; float y = 0; public HobbyRecyclerView(@NonNull Context context) { super(context); } public HobbyRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(context,attrs); } public HobbyRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context,attrs); } /** * 初始化 * @param context * @param attrs */ private void init(Context context, AttributeSet attrs) { mRangeRectf = new RectF(); // region = new Region(); mRangPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mRangPaint.setStyle(Paint.Style.FILL); TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.HobbyRecyclerView); showMode = ta.getInteger(R.styleable.HobbyRecyclerView_scrollBarMode,1); ta.recycle(); addOnScrollListener(onScrollListener); } @Override protected void onMeasure(int widthSpec, int heightSpec) { if(showMode != 1){ int width = MeasureSpec.getSize(widthSpec); scrollBarWidth = width / scrollWidthWeight;//取10分之一 scrollWidthSpace = scrollBarWidth / 10; //獲取間隙 childWidth = (int) (width - scrollBarWidth); scrollBarWidth = scrollBarWidth - 2 * scrollWidthSpace; for (int i = 0; i < getChildCount(); i++) { measureChild(getChildAt(i),childWidth,heightSpec); getChildAt(i).getLayoutParams().width = childWidth; } setMeasuredDimension(width,heightSpec); }else { super.onMeasure(widthSpec, heightSpec); } } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); visualHeight = getMeasuredHeight(); childViewAllHeight = getChildAt(2).getHeight() * getAdapter().getItemCount(); range = 0; if(childViewAllHeight != 0){ range = visualHeight / childViewAllHeight; } scrollBarHeight = range * visualHeight; } @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); drawRange(canvas); } private void drawRange(Canvas canvas){ if(canvas == null) return; mRangeRectf.set(childWidth + scrollWidthSpace,yScrollOffset,childWidth + scrollBarWidth ,yScrollOffset + scrollBarHeight); if(isFocus) { mRangPaint.setColor(Color.parseColor("#2386BF")); }else{ mRangPaint.setColor(Color.parseColor("#2EB3FF")); } canvas.drawRect(mRangeRectf,mRangPaint); Log.i("tag" , "yScrollOffset ------- " + yScrollOffset); Log.i("tag" , "scrollBarHeight ------- " + scrollBarHeight); Log.i("tag" , "yScrollOffset ------- " + yScrollOffset); } private RecyclerView.OnScrollListener onScrollListener = new OnScrollListener() { @Override public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); } @Override public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); yScrollOffset += dy * range; } }; @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: //獲取屏幕上點擊的座標 x = event.getX(); y = event.getY(); if(x >= mRangeRectf.left && x <= mRangeRectf.right && y >= mRangeRectf.top && y <= mRangeRectf.bottom){ isFocus = true; invalidate(); } break; case MotionEvent.ACTION_MOVE: if(x >= mRangeRectf.left && x <= mRangeRectf.right && y >= mRangeRectf.top && y <= mRangeRectf.bottom){ float diffValue = event.getY() - y; scrollBy(0, (int) ((diffValue/visualHeight) * childViewAllHeight)); y = event.getY(); } break; case MotionEvent.ACTION_UP: isFocus = false; invalidate(); break; } if(x >= childWidth && x <= getMeasuredWidth() && y >= 0 && y <= getMeasuredHeight()){ return true; }else return super.onTouchEvent(event); } /** * //當前RcyclerView顯示區域的高度。水平列表屏幕從左側到右側顯示範圍 int extent = this.computeHorizontalScrollExtent(); //總體的高度,注意是總體,包括在顯示區域以外的。 int range = this.computeHorizontalScrollRange(); //已經向下滾動的距離,爲0時表示已處於頂部。 int offset = this.computeHorizontalScrollOffset(); */ }
是否是很簡單呢?code
ok有什麼問題本身看吧。若是你看到最後幾行註釋了,那麼你會疑問,那是由於我看了這個文章 xml