您好,登錄后才能下訂單哦!
這篇“怎么使用Android itemDecoration接口實現吸頂懸浮標題”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“怎么使用Android itemDecoration接口實現吸頂懸浮標題”文章吧。
1.設置一個懸浮的視圖掛在recycleView頂部,隨著item的移動位置,懸浮標題自動跟隨移動或者是保持原地不動。
2.使用recyclerView的ItemDecoration,給指定的item設置不同的itemDecoration,并且跟隨item的移動而移動或者保持不變。
本文采用第二種方式實現,效果圖:
這是個接口,一共有六個方法:
public static abstract class ItemDecoration { /** * Draw any appropriate decorations into the Canvas supplied to the RecyclerView. * Any content drawn by this method will be drawn before the item views are drawn, * and will thus appear underneath the views. * * @param c Canvas to draw into * @param parent RecyclerView this ItemDecoration is drawing into * @param state The current state of RecyclerView */ public void onDraw(Canvas c, RecyclerView parent, State state) { onDraw(c, parent); } /** * Draw any appropriate decorations into the Canvas supplied to the RecyclerView. * Any content drawn by this method will be drawn after the item views are drawn * and will thus appear over the views. * * @param c Canvas to draw into * @param parent RecyclerView this ItemDecoration is drawing into * @param state The current state of RecyclerView. */ public void onDrawOver(Canvas c, RecyclerView parent, State state) { onDrawOver(c, parent); } /** * Retrieve any offsets for the given item. Each field of <code>outRect</code> specifies * the number of pixels that the item view should be inset by, similar to padding or margin. * The default implementation sets the bounds of outRect to 0 and returns. * * <p> * If this ItemDecoration does not affect the positioning of item views, it should set * all four fields of <code>outRect</code> (left, top, right, bottom) to zero * before returning. * * <p> * If you need to access Adapter for additional data, you can call * {@link RecyclerView#getChildAdapterPosition(View)} to get the adapter position of the * View. * * @param outRect Rect to receive the output. * @param view The child view to decorate * @param parent RecyclerView this ItemDecoration is decorating * @param state The current state of RecyclerView. */ public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state) { getItemOffsets(outRect, ((LayoutParams) view.getLayoutParams()).getViewLayoutPosition(), parent); } /** * @deprecated * Override {@link #onDrawOver(Canvas, RecyclerView, RecyclerView.State)} */ @Deprecated public void onDrawOver(Canvas c, RecyclerView parent) { } /** * @deprecated * Override {@link #onDraw(Canvas, RecyclerView, RecyclerView.State)} */ @Deprecated public void onDraw(Canvas c, RecyclerView parent) { } /** * @deprecated * Use {@link #getItemOffsets(Rect, View, RecyclerView, State)} */ @Deprecated public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) { outRect.set(0, 0, 0, 0); } }
其中有三個方法是@deprecated的,那么我們只需要看以下三個方法:
public void onDraw(Canvas c, RecyclerView parent, State state) { onDraw(c, parent); } public void onDrawOver(Canvas c, RecyclerView parent, State state) { onDrawOver(c, parent); } public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state) { getItemOffsets(outRect, ((LayoutParams) view.getLayoutParams()).getViewLayoutPosition(), parent); }
第一個方法的意思是繪制分割線本身;
第二個方法是在item項目繪制完成之后進行的繪制操作(這個會覆蓋在item上面);
第三個方法是設置分割線的左間距,上間距,右間距,下間距,保存在outRect中。
如圖所示:
其中最底層黃色部分大小是getItemOffsets方法返回的itemDecoration的矩陣設置邊距寬度,onDraw方法根據設置的間距寬度來進行繪制黃色區域,其中棕紅色部分是onDrawOver方法覆蓋繪制在item上層的部分。
我們給每個需要title的item設置rect.top = titleHeight(標題欄高度);其他的間距可以先不考慮,不重要;
重寫onDraw方法,繪制我們的itemDecoration標題欄;
我們需要重寫onDrawOver方法,在滑動的時候去判斷,
1)如果頂部標題區域是在該標題的items范圍之內的滑動的話,那么我們需要覆蓋繪制一個處于recyclerView.getpaddingTop位置的title,這樣的話這個范圍內滑動就有一個懸停的標題欄;
2)如果頂部的標題欄區域恰好下面緊跟著下一個標題欄,那么繼續向上滑動的時候,需要下面的標題欄把上面的標題欄頂出界面之外。那么繪制的頂部標題欄的起始位置就是所處的item.bottom - titleHeight的位置。
使用以上三個步驟就可以做出一個流暢并且定制化很高的懸浮標題欄功能了。
class MyDecoration(context: Context): RecyclerView.ItemDecoration() { var mPaint:Paint? = null var mPaint2:Paint? = null var mTextPaint:Paint? = null var mTitleHeight:Int? = null var mTitleHeight2:Int? = null var mTitleTextSize:Float? = null init { mTitleHeight = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, 30f, context.getResources().getDisplayMetrics() ).toInt() mTitleHeight2 = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, 3f, context.getResources().getDisplayMetrics() ).toInt() mTitleTextSize = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_SP, 16f, context.getResources().getDisplayMetrics() ) mTextPaint = Paint() mTextPaint?.let { it.setTextSize(mTitleTextSize!!) it.setAntiAlias(true) it.setColor(Color.WHITE) } mPaint = Paint() mPaint?.let { it.setAntiAlias(true) it.setColor(Color.RED) } mPaint2 = Paint() mPaint2?.let { it.setAntiAlias(true) it.setColor(Color.BLUE) } } /** * recyclerView繪制onDraw -> item.onDraw -> onDrawOver */ override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) { for (index in 0 until parent.childCount) { val childView = parent.getChildAt(index) childView?.let { val rect = Rect() val position = parent.getChildAdapterPosition(it) if (isTitleItem(position)) { rect.top = childView.top - mTitleHeight!! rect.bottom = childView.top } else { rect.top = childView.top - mTitleHeight2!! rect.bottom = childView.top } rect.left = parent.paddingLeft rect.right = parent.width - parent.paddingRight if (isTitleItem(position)) { mPaint?.let { it1 -> c.drawRect(rect, it1) } mTextPaint?.let { it3 -> c.drawText( getTitleStr(position), 0f, rect.top.toFloat() + (mTitleHeight?.div(2.00f)?:0f), it3)} } else { mPaint2?.let { it1 -> c.drawRect(rect, it1) } } } } } /** * recyclerView繪制onDraw -> item.onDraw -> onDrawOver * 繪制覆蓋在item上面的分割線效果 */ override fun onDrawOver(c: Canvas, parent: RecyclerView, state: RecyclerView.State) { val childView = parent.getChildAt(0) var nextView:View? = null; if (1 < parent.childCount) { nextView = parent.getChildAt(1) } childView?.let { val rect = Rect() val position = parent.getChildAdapterPosition(it) mTitleHeight?.let { height -> if (nextView != null && it.bottom - height < parent.paddingTop && isTitleItem(parent.getChildAdapterPosition(nextView)) && !isSameTitle(parent.getChildAdapterPosition(nextView),position)) { rect.top = it.bottom - height rect.bottom = it.bottom } else { rect.top = parent.paddingTop rect.bottom = rect.top + height } } rect.left = parent.paddingLeft rect.right = parent.width - parent.paddingRight mPaint?.let { it1 -> c.drawRect(rect, it1) } mTextPaint?.let { it3 -> c.drawText( getTitleStr(position), 0f, rect.top + (mTitleHeight?.div(2.00f)?:0f), it3)} } } /** * 用于設置item周圍的偏移量的,類似于設置padding喝margin效果, * 空出的效果用于繪制分割線 */ override fun getItemOffsets( outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State ) { val position:Int = parent.getChildAdapterPosition(view) if (position % 4 == 0) { outRect.top = mTitleHeight!! } else{ outRect.top = mTitleHeight2!! } } fun isTitleItem(position: Int):Boolean { return position % 4 == 0 } fun getTitleStr(position: Int):String { return "標題:${position / 4}" } fun isSameTitle(position1: Int,position2: Int):Boolean { return (position1 / 4) == (position2 / 4) } }
以上就是關于“怎么使用Android itemDecoration接口實現吸頂懸浮標題”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。