android堆叠效果相册_Android自定义ViewGroup实现堆叠头像的点赞Layout

简介

这样的点赞列表怎么样?之前做社区的时候也有类似的点赞列表,但是没有这样重叠,一个小小的改变,个人感觉逼格提高不少。

这个很有规则,就是后一个头像会覆盖一部分到前一个头像上,头像多了就像一串糖葫芦了。

这个实现起来不难,自定义ViewGroup,关键重写onLayout方法。

实现

自定义属性

属性名

说明

默认值

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,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方式去设置数据源。

下载

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值