簡介

這樣的點贊列表怎么樣?之前做社區的時候也有類似的點贊列表,但是沒有這樣重疊,一個小小的改變,個人感覺逼格提高不少。
這個很有規則,就是后一個頭像會覆蓋一部分到前一個頭像上,頭像多了就像一串糖葫蘆了。
這個實現起來不難,自定義ViewGroup,關鍵重寫onLayout方法。
關于自定義控件的基礎知識可以看一看這個,整理的很詳細: https://github.com/GcsSloop/AndroidNote
實現
自定義屬性
| 屬性名 | 說明 | 默認值 |
|---|---|---|
| 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;//當前行總寬度 int rawHeight = 0;// 當前行高 int rowIndex = 0;//當前行位置 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; } //這里調用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;//當前行位置 View childView; for( int w = 0, count = getChildCount(); w < count; w++ ){ childView = getChildAt(w); if(childView.getVisibility() == GONE) continue; MarginLayoutParams lp = (MarginLayoutParams) childView.getLayoutParams(); // 如果加上當前子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方式去設置數據源。
下載
https://github.com/LineChen/PileLayout
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。
新聞熱點
疑難解答