一、测试效果未成功
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
package
cn.app.meiya.aa.widget;
import
android.content.Context;
import
android.util.AttributeSet;
import
android.view.View;
import
android.view.ViewGroup;
import
java.util.ArrayList;
import
java.util.List;
/**
* 类似话题标签的流式布局,测试效果无效
* http://www.apkbus.com/android-239725-1-1.html
* Created by lonshine on 15/7/16.
*/
public
class
TopicFlowLayout
extends
ViewGroup {
//存储所有子View
private
List<List<View>> mAllChildViews =
new
ArrayList<>();
//每一行的高度
private
List<Integer> mLineHeight =
new
ArrayList<>();
public
TopicFlowLayout(Context context) {
this
(context,
null
);
// TODO Auto-generated constructor stub
}
public
TopicFlowLayout(Context context, AttributeSet attrs) {
this
(context, attrs,
0
);
// TODO Auto-generated constructor stub
}
public
TopicFlowLayout(Context context, AttributeSet attrs,
int
defStyle) {
super
(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
@Override
protected
void
onMeasure(
int
widthMeasureSpec,
int
heightMeasureSpec) {
// TODO Auto-generated method stub
//父控件传进来的宽度和高度以及对应的测量模式
int
sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
int
modeWidth = MeasureSpec.getMode(widthMeasureSpec);
int
sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
int
modeHeight = MeasureSpec.getMode(heightMeasureSpec);
//如果当前ViewGroup的宽高为wrap_content的情况
int
width =
0
;
//自己测量的 宽度
int
height =
0
;
//自己测量的高度
//记录每一行的宽度和高度
int
lineWidth =
0
;
int
lineHeight =
0
;
//获取子view的个数
int
childCount = getChildCount();
for
(
int
i =
0
; i < childCount; i++) {
View child = getChildAt(i);
//测量子View的宽和高
measureChild(child, widthMeasureSpec, heightMeasureSpec);
//得到LayoutParams
MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();
//子View占据的宽度
int
childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
//子View占据的高度
int
childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
//换行时候
if
(lineWidth + childWidth > sizeWidth) {
//对比得到最大的宽度
width = Math.max(width, lineWidth);
//重置lineWidth
lineWidth = childWidth;
//记录行高
height += lineHeight;
lineHeight = childHeight;
}
else
{
//不换行情况
//叠加行宽
lineWidth += childWidth;
//得到最大行高
lineHeight = Math.max(lineHeight, childHeight);
}
//处理最后一个子View的情况
if
(i == childCount -
1
) {
width = Math.max(width, lineWidth);
height += lineHeight;
}
}
//wrap_content
setMeasuredDimension(modeWidth == MeasureSpec.EXACTLY ? sizeWidth : width,
modeHeight == MeasureSpec.EXACTLY ? sizeHeight : height);
super
.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected
void
onLayout(
boolean
changed,
int
l,
int
t,
int
r,
int
b) {
// TODO Auto-generated method stub
mAllChildViews.clear();
mLineHeight.clear();
//获取当前ViewGroup的宽度
int
width = getWidth();
int
lineWidth =
0
;
int
lineHeight =
0
;
//记录当前行的view
List<View> lineViews =
new
ArrayList<View>();
int
childCount = getChildCount();
for
(
int
i =
0
; i < childCount; i++) {
View child = getChildAt(i);
MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
int
childWidth = child.getMeasuredWidth();
int
childHeight = child.getMeasuredHeight();
//如果需要换行
if
(childWidth + lineWidth + lp.leftMargin + lp.rightMargin > width) {
//记录LineHeight
mLineHeight.add(lineHeight);
//记录当前行的Views
mAllChildViews.add(lineViews);
//重置行的宽高
lineWidth =
0
;
lineHeight = childHeight + lp.topMargin + lp.bottomMargin;
//重置view的集合
lineViews =
new
ArrayList();
}
lineWidth += childWidth + lp.leftMargin + lp.rightMargin;
lineHeight = Math.max(lineHeight, childHeight + lp.topMargin + lp.bottomMargin);
lineViews.add(child);
}
//处理最后一行
mLineHeight.add(lineHeight);
mAllChildViews.add(lineViews);
//设置子View的位置
int
left =
0
;
int
top =
0
;
//获取行数
int
lineCount = mAllChildViews.size();
for
(
int
i =
0
; i < lineCount; i++) {
//当前行的views和高度
lineViews = mAllChildViews.get(i);
lineHeight = mLineHeight.get(i);
for
(
int
j =
0
; j < lineViews.size(); j++) {
View child = lineViews.get(j);
//判断是否显示
if
(child.getVisibility() == View.GONE) {
continue
;
}
MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
int
cLeft = left + lp.leftMargin;
int
cTop = top + lp.topMargin;
int
cRight = cLeft + child.getMeasuredWidth();
int
cBottom = cTop + child.getMeasuredHeight();
//进行子View进行布局
child.layout(cLeft, cTop, cRight, cBottom);
left += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
}
left =
0
;
top += lineHeight;
}
}
/**
* 与当前ViewGroup对应的LayoutParams
*/
@Override
public
LayoutParams generateLayoutParams(AttributeSet attrs) {
// TODO Auto-generated method stub
return
new
MarginLayoutParams(getContext(), attrs);
}
}
|
用法:
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
|
<font color=
"#362e2b"
><font style=
"background-color:rgb(255, 255, 255)"
><font face=
"Arial"
><font style=
"font-size:14px"
>
package
com.czm.flowlayout;
import
android.app.Activity;
import
android.graphics.Color;
import
android.os.Bundle;
import
android.view.ViewGroup.LayoutParams;
import
android.view.ViewGroup.MarginLayoutParams;
import
android.widget.TextView;
/**
*
* @author caizhiming
* @created on 2015-4-13
*/
public
class
MainActivity
extends
Activity {
private
String mNames[] = {
"welcome"
,
"android"
,
"TextView"
,
"apple"
,
"jamy"
,
"kobe bryant"
,
"jordan"
,
"layout"
,
"viewgroup"
,
"margin"
,
"padding"
,
"text"
,
"name"
,
"type"
,
"search"
,
"logcat"
};
private
XCFlowLayout mFlowLayout;
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initChildViews();
}
private
void
initChildViews() {
// TODO Auto-generated method stub
mFlowLayout = (XCFlowLayout) findViewById(R.id.flowlayout);
MarginLayoutParams lp =
new
MarginLayoutParams(
LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
lp.leftMargin =
5
;
lp.rightMargin =
5
;
lp.topMargin =
5
;
lp.bottomMargin =
5
;
for
(
int
i =
0
; i < mNames.length; i ++){
TextView view =
new
TextView(
this
);
view.setText(mNames[i]);
view.setTextColor(Color.WHITE);
view.setBackgroundDrawable(getResources().getDrawable(R.drawable.textview_bg));
mFlowLayout.addView(view,lp);
}
}
}</font></font></font></font>
|
二、测试可用
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
package
cn.app.meiya.aa.widget;
import
android.content.Context;
import
android.util.AttributeSet;
import
android.view.View;
import
android.view.ViewGroup;
/**
* http://www.bkjia.com/Androidjc/1013458.html
* Created by lonshine on 15/7/16.
*/
public
class
FlowLayout
extends
ViewGroup {
private
float
mVerticalSpacing;
//每个item纵向间距
private
float
mHorizontalSpacing;
//每个item横向间距
public
FlowLayout(Context context) {
super
(context);
}
public
FlowLayout(Context context, AttributeSet attrs) {
super
(context, attrs);
}
public
void
setHorizontalSpacing(
float
pixelSize) {
mHorizontalSpacing = pixelSize;
}
public
void
setVerticalSpacing(
float
pixelSize) {
mVerticalSpacing = pixelSize;
}
@Override
protected
void
onMeasure(
int
widthMeasureSpec,
int
heightMeasureSpec) {
int
selfWidth = resolveSize(
0
, widthMeasureSpec);
int
paddingLeft = getPaddingLeft();
int
paddingTop = getPaddingTop();
int
paddingRight = getPaddingRight();
int
paddingBottom = getPaddingBottom();
int
childLeft = paddingLeft;
int
childTop = paddingTop;
int
lineHeight =
0
;
//通过计算每一个子控件的高度,得到自己的高度
for
(
int
i =
0
, childCount = getChildCount(); i < childCount; ++i) {
View childView = getChildAt(i);
LayoutParams childLayoutParams = childView.getLayoutParams();
childView.measure(
getChildMeasureSpec(widthMeasureSpec, paddingLeft + paddingRight,
childLayoutParams.width),
getChildMeasureSpec(heightMeasureSpec, paddingTop + paddingBottom,
childLayoutParams.height));
int
childWidth = childView.getMeasuredWidth();
int
childHeight = childView.getMeasuredHeight();
lineHeight = Math.max(childHeight, lineHeight);
if
(childLeft + childWidth + paddingRight > selfWidth) {
childLeft = paddingLeft;
childTop += mVerticalSpacing + lineHeight;
lineHeight = childHeight;
}
else
{
childLeft += childWidth + mHorizontalSpacing;
}
}
int
wantedHeight = childTop + lineHeight + paddingBottom;
setMeasuredDimension(selfWidth, resolveSize(wantedHeight, heightMeasureSpec));
}
@Override
protected
void
onLayout(
boolean
changed,
int
l,
int
t,
int
r,
int
b) {
int
myWidth = r - l;
int
paddingLeft = getPaddingLeft();
int
paddingTop = getPaddingTop();
int
paddingRight = getPaddingRight();
int
childLeft = paddingLeft;
int
childTop = paddingTop;
int
lineHeight =
0
;
//根据子控件的宽高,计算子控件应该出现的位置。
for
(
int
i =
0
, childCount = getChildCount(); i < childCount; ++i) {
View childView = getChildAt(i);
if
(childView.getVisibility() == View.GONE) {
continue
;
}
int
childWidth = childView.getMeasuredWidth();
int
childHeight = childView.getMeasuredHeight();
lineHeight = Math.max(childHeight, lineHeight);
if
(childLeft + childWidth + paddingRight > myWidth) {
childLeft = paddingLeft;
childTop += mVerticalSpacing + lineHeight;
lineHeight = childHeight;
}
childView.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
childLeft += childWidth + mHorizontalSpacing;
}
}
}
|
本文转自 glblong 51CTO博客,原文链接:http://blog.51cto.com/glblong/1675221,如需转载请自行联系原作者