先上完整代码:
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78public 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()阶段开始
定义了四个量:
复制代码
1
2
3
4
5int widthUse = 0;//使用了多少宽度 int heightUse = 0;//使用了多少高度 int lineMaxWidth = 0; //当前最大宽度 int lineMaxHeight = 0;//当前最大高度
这个布局是个横向排列的过程,我们用一个widthUse
来记录当前行横向使用的宽度,则计算下个子View位置时候,只需在此基础上累加即可。
而lineMaxHeight
用来记录当前行的子View中的最大高度,当换行时候传递给heightUse
,使下一阶段的子View添加下沉高度。
这段代码是什么意义:
复制代码
1
2measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, heightUse);
这其实是安卓帮我们做了一个自动计算的过程:
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26LayoutParams 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()阶段
循环设置布局参数
复制代码
1
2
3
4
5
6for (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布局先上完整代码:的全部内容,更多相关如何自定义一个简单内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复