Android自定義ViewGroup實現(xiàn)堆疊頭像的點贊Layout
簡介
這樣的點贊列表怎么樣?之前做社區(qū)的時候也有類似的點贊列表,但是沒有這樣重疊,一個小小的改變,個人感覺逼格提高不少。
這個很有規(guī)則,就是后一個頭像會覆蓋一部分到前一個頭像上,頭像多了就像一串糖葫蘆了。
這個實現(xiàn)起來不難,自定義ViewGroup,關(guān)鍵重寫onLayout方法。
關(guān)于自定義控件的基礎(chǔ)知識可以看一看這個,整理的很詳細: https://github.com/GcsSloop/AndroidNote
實現(xiàn)
自定義屬性
屬性名 | 說明 | 默認值 |
---|---|---|
vertivalSpace | 行距 | 4dp |
pileWidth | 重疊寬度 | 10dp |
onMeasure方法,每行的寬度不再是child的寬度和了,而是要減掉重疊部分的寬度和
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec); int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec); int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec); int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec); //AT_MOST int width = 0; int height = 0; int rawWidth = 0;//當(dāng)前行總寬度 int rawHeight = 0;// 當(dāng)前行高 int rowIndex = 0;//當(dāng)前行位置 int count = getChildCount(); for (int i = 0; i < count; i++) { View child = getChildAt(i); if(child.getVisibility() == GONE){ if(i == count - 1){ //最后一個child height += rawHeight; width = Math.max(width, rawWidth); } continue; } //這里調(diào)用measureChildWithMargins 而不是measureChild measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0); MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams(); int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin; int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin; if(rawWidth + childWidth - (rowIndex > 0 ? pileWidth : 0)> widthSpecSize - getPaddingLeft() - getPaddingRight()){ //換行 width = Math.max(width, rawWidth); rawWidth = childWidth; height += rawHeight + vertivalSpace; rawHeight = childHeight; rowIndex = 0; } else { rawWidth += childWidth; if(rowIndex > 0){ rawWidth -= pileWidth; } rawHeight = Math.max(rawHeight, childHeight); } if(i == count - 1){ width = Math.max(rawWidth, width); height += rawHeight; } rowIndex++; } setMeasuredDimension( widthSpecMode == MeasureSpec.EXACTLY ? widthSpecSize : width + getPaddingLeft() + getPaddingRight(), heightSpecMode == MeasureSpec.EXACTLY ? heightSpecSize : height + getPaddingTop() + getPaddingBottom() ); }
onLayout 每一行,第一個正常放,之后的重疊放
@Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int viewWidth = r - l; int leftOffset = getPaddingLeft(); int topOffset = getPaddingTop(); int rowMaxHeight = 0; int rowIndex = 0;//當(dāng)前行位置 View childView; for( int w = 0, count = getChildCount(); w < count; w++ ){ childView = getChildAt(w); if(childView.getVisibility() == GONE) continue; MarginLayoutParams lp = (MarginLayoutParams) childView.getLayoutParams(); // 如果加上當(dāng)前子View的寬度后超過了ViewGroup的寬度,就換行 int occupyWidth = lp.leftMargin + childView.getMeasuredWidth() + lp.rightMargin; if(leftOffset + occupyWidth + getPaddingRight() > viewWidth){ leftOffset = getPaddingLeft(); // 回到最左邊 topOffset += rowMaxHeight + vertivalSpace; // 換行 rowMaxHeight = 0; rowIndex = 0; } int left = leftOffset + lp.leftMargin; int top = topOffset + lp.topMargin; int right = leftOffset+ lp.leftMargin + childView.getMeasuredWidth(); int bottom = topOffset + lp.topMargin + childView.getMeasuredHeight(); childView.layout(left, top, right, bottom); // 橫向偏移 leftOffset += occupyWidth; // 試圖更新本行最高View的高度 int occupyHeight = lp.topMargin + childView.getMeasuredHeight() + lp.bottomMargin; if(rowIndex != count - 1){ leftOffset -= pileWidth;//這里控制重疊位置 } rowMaxHeight = Math.max(rowMaxHeight, occupyHeight); rowIndex++; } }
效果圖
因為這個一般只會顯示一行,所以暫時沒有通過setAdapter方式去設(shè)置數(shù)據(jù)源。
下載
https://github.com/LineChen/PileLayout
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android自定義ViewGroup實現(xiàn)帶箭頭的圓角矩形菜單
- Android自定義ViewGroup實現(xiàn)標簽浮動效果
- Android自定義ViewGroup之實現(xiàn)FlowLayout流式布局
- Android App開發(fā)中自定義View和ViewGroup的實例教程
- 一篇文章弄懂Android自定義viewgroup的相關(guān)難點
- Android應(yīng)用開發(fā)中自定義ViewGroup的究極攻略
- Android自定義ViewGroup實現(xiàn)受邊界限制的滾動操作(3)
- Android動畫效果之自定義ViewGroup添加布局動畫(五)
- Android自定義ViewGroup的實現(xiàn)方法
- Android自定義ViewGroup實現(xiàn)朋友圈九宮格控件
相關(guān)文章
Android BottomSheetDialog實現(xiàn)底部對話框的示例
這篇文章主要介紹了Android BottomSheetDialog實現(xiàn)底部對話框的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-06-06Android學(xué)習(xí)筆記之應(yīng)用單元測試實例分析
這篇文章主要介紹了Android學(xué)習(xí)筆記之應(yīng)用單元測試,結(jié)合實例形式較為詳細的分析了Android單元測試的實現(xiàn)原理與具體步驟,具有一定參考借鑒價值,需要的朋友可以參考下2015-11-11Android中常用的三個Dialog彈窗總結(jié)解析
自己雖然一直使用過dialog,但是一直都是復(fù)制、粘貼;不清楚dialog的具體用途,這次趁著有時間,總結(jié)一下具體用法,感興趣的朋友跟著小編來看看吧2021-10-10Android自定義Dialog實現(xiàn)文字動態(tài)加載效果
這篇文章主要為大家詳細介紹了Android自定義Dialog實現(xiàn)文字動態(tài)加載效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-08-08Android Service判斷設(shè)備聯(lián)網(wǎng)狀態(tài)詳解
本文主要介紹Android Service判斷聯(lián)網(wǎng)狀態(tài),這里提供了相關(guān)資料并附有示例代碼,有興趣的小伙伴可以參考下,幫助開發(fā)相關(guān)應(yīng)用功能2016-08-08Diycode開源項目實例搭建上拉加載和下拉刷新的Fragment
這篇文章主要介紹了Diycode開源項目實例搭建上拉加載和下拉刷新的Fragment以及相關(guān)的代碼分享。2017-11-11