我是靠谱客的博主 魁梧香水,最近开发中收集的这篇文章主要介绍如何自定义一个简单的自动换行的TagLayout布局先上完整代码:,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

在这里插入图片描述

先上完整代码:

public class TagLayout extends ViewGroup {

  List<Rect> childrenBounds = new ArrayList<>();

  public TagLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  @Override
  protected void onLayout(boolean changed, int l, int t, int r, int b) {
    for (int i = 0; i < getChildCount(); i++) {
      View child = getChildAt(i);
      Rect childBound = childrenBounds.get(i);
      child.layout(childBound.left, childBound.top, childBound.right, childBound.bottom);
    }
  }

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    int lineMaxWidth = 0;
    int heightUse = 0;
    int widthUse = 0;
    int lineMaxHeight = 0;

    int specMode=MeasureSpec.getMode(widthMeasureSpec);

    int specWidth = MeasureSpec.getSize(widthMeasureSpec);

    for (int i = 0; i < getChildCount(); i++) {
      View child = getChildAt(i);

      measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, heightUse);

      if (specMode!=MeasureSpec.UNSPECIFIED&&widthUse + child.getMeasuredWidth() > specWidth) {
        // 另起一行
        widthUse = 0;
        heightUse += lineMaxHeight;
        lineMaxHeight=0;
        measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, heightUse);
      }

      Rect childBound;
      if (childrenBounds.size() <= i) {
        childBound = new Rect();
        childrenBounds.add(childBound);
      } else {
        childBound = childrenBounds.get(i);
      }

      childBound.set(
          widthUse,
          heightUse,
          widthUse + getMeasuredWidth(),
          heightUse + getMeasuredHeight());

      widthUse += child.getMeasuredWidth();
      lineMaxWidth = Math.max(lineMaxWidth, widthUse);
      lineMaxHeight = Math.max(lineMaxHeight, child.getMeasuredHeight());
    }

    int width = lineMaxWidth;
    int height = lineMaxHeight+heightUse;
    setMeasuredDimension(width, height);
  }

  @Override
  public LayoutParams generateLayoutParams(AttributeSet attrs) {
    return new MarginLayoutParams(getContext(), attrs);
  }
}

## 准备工作
定义一个容器来存储子View的位置信息:
```java
  List<Rect> childrenBounds = new ArrayList<>();

先从onMeasure()阶段开始

定义了四个量:

    int widthUse = 0;//使用了多少宽度
    int heightUse = 0;//使用了多少高度
    int lineMaxWidth = 0; //当前最大宽度
    int lineMaxHeight = 0;//当前最大高度

这个布局是个横向排列的过程,我们用一个widthUse来记录当前行横向使用的宽度,则计算下个子View位置时候,只需在此基础上累加即可。
lineMaxHeight用来记录当前行的子View中的最大高度,当换行时候传递给heightUse,使下一阶段的子View添加下沉高度。

这段代码是什么意义:

   measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, heightUse);

这其实是安卓帮我们做了一个自动计算的过程:

    LayoutParams layoutParams = child.getLayoutParams();

      int specWidthMode = MeasureSpec.getMode(widthMeasureSpec);
      int specWidthSize = MeasureSpec.getSize(widthMeasureSpec);

      int childWidthMode;
      int childWidthSize;

      switch (layoutParams.width) {
        case LayoutParams.MATCH_PARENT:
          switch (specWidthMode) {
            case MeasureSpec.EXACTLY:
            case MeasureSpec.AT_MOST:
              childWidthMode = MeasureSpec.EXACTLY;
              childWidthSize = specWidthSize - useWidth;
              break;
            case MeasureSpec.UNSPECIFIED:
              childWidthMode = MeasureSpec.UNSPECIFIED;
              childWidthSize = 0;
              break;
          }
          break;
        case LayoutParams.WRAP_CONTENT:
          break;
      }

可以类比为如上的代码,根据开发者传入的参数类型进行数值的自动适配

onLayout()阶段

循环设置布局参数

    for (int i = 0; i < getChildCount(); i++) {
      View child = getChildAt(i);
      Rect childBound = childrenBounds.get(i);
      child.layout(childBound.left, childBound.top, childBound.right, childBound.bottom);
    }

最后

以上就是魁梧香水为你收集整理的如何自定义一个简单的自动换行的TagLayout布局先上完整代码:的全部内容,希望文章能够帮你解决如何自定义一个简单的自动换行的TagLayout布局先上完整代码:所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(63)

评论列表共有 0 条评论

立即
投稿
返回
顶部