源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

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

  • 时间:2022-09-16 09:50 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:Android自定义ViewGroup实现堆叠头像的点赞Layout
[b]简介[/b] [img]http://files.jb51.net/file_images/article/201710/201710200926504.png[/img] 这样的点赞列表怎么样?之前做社区的时候也有类似的点赞列表,但是没有这样重叠,一个小小的改变,个人感觉逼格提高不少。 这个很有规则,就是后一个头像会覆盖一部分到前一个头像上,头像多了就像一串糖葫芦了。 这个实现起来不难,自定义ViewGroup,关键重写onLayout方法。 关于自定义控件的基础知识可以看一看这个,整理的很详细: [url=https://github.com/GcsSloop/AndroidNote]https://github.com/GcsSloop/AndroidNote[/url] [b]实现[/b] [b]自定义属性[/b]
属性名 说明 默认值
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++;
    }
  }

效果图 [img]http://files.jb51.net/file_images/article/201710/201710200926505.png[/img] 因为这个一般只会显示一行,所以暂时没有通过setAdapter方式去设置数据源。 下载 [url=https://github.com/LineChen/PileLayout]https://github.com/LineChen/PileLayout[/url] 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程素材网。
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部