当前位置: 移动技术网 > 移动技术>移动开发>Android > Android自定义ViewGroup实现堆叠头像的点赞Layout

Android自定义ViewGroup实现堆叠头像的点赞Layout

2019年07月24日  | 移动技术网移动技术  | 我要评论
简介 这样的点赞列表怎么样?之前做社区的时候也有类似的点赞列表,但是没有这样重叠,一个小小的改变,个人感觉逼格提高不少。 这个很有规则,就是后一个头像会覆盖一部分到

简介

这里写图片描述

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

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

这个实现起来不难,自定义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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网