Android自定义View(一)流失布局FlowLayout
2018-07-28 本文已影响35人
digtal_
A18823137F61E6A21141DB7FEF73A42B.png
实现步骤
1.写一个类FlowLayout 继承ViewGroup
2.在onMeasure方法中计算得到控件的宽高,思路就是计算每个子孩子的宽高当子孩子的宽度相加大于控件宽度就换行,高度累加
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
//定义控件宽度
int width = 0;
//定义控件高度
int height = 0;
//定义每行最大宽度
int lineWidth = 0;
//定义每行最大高度
int lineHeight = 0;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
measureChild(child,widthMeasureSpec, heightMeasureSpec);
MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
if (lineWidth + childWidth > widthSize) {//大于控件宽度换行
width = Math.max(lineWidth, width);
height += lineHeight;
lineWidth = childWidth;
lineHeight = childHeight;
} else {
lineWidth += childWidth;
lineHeight = Math.max(childHeight, lineHeight);
}
if (i == getChildCount() - 1) {//如果是最后一个子控件要计算他的宽高再算进去
width = Math.max(lineWidth, width);
height += lineHeight;
}
}
setMeasuredDimension(widthMode == MeasureSpec.EXACTLY ? widthSize : width,
heightMode == MeasureSpec.EXACTLY ? heightSize : height);
Log.e("width", "width = " + width);
Log.e("height", "height = " + height);
}
3.其中要注意的是getLayoutParams方法要在类中重写generateLayoutParams方法否则是拿不到子孩子的margin值
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new MarginLayoutParams(getContext(), attrs);
}
4.最后就是子孩子的具体怎么摆放了思路和测量中的方法差不多
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
//定义每行最大宽度
int lineWidth = 0;
//定义每行最大高度
int lineHeight = 0;
int left = 0;
int top = 0;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
if (lineWidth + childWidth > getMeasuredWidth()) {//大于控件宽度换行
top += lineHeight;
//换行把left值为0
left = 0;
lineWidth = childWidth;
lineHeight = childHeight;
} else {
lineWidth += childWidth;
lineHeight = Math.max(childHeight, lineHeight);
}
int lc = left + lp.leftMargin;
int tc = top + lp.topMargin;
int rc = lc + child.getMeasuredWidth();
int bc = tc + child.getMeasuredHeight();
child.layout(lc, tc, rc, bc);
left += childWidth;
}
}
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimary">
<com.chinamall21.mobile.animstudy.view.FlowLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
style="@style/style_flow"
android:text="it工程师"/>
<TextView
style="@style/style_flow"
android:text="ANDORID"/>
<TextView
style="@style/style_flow"
android:text="IOS"/>
<TextView
style="@style/style_flow"
android:text="JAVA开发"/>
<TextView
style="@style/style_flow"
android:text="产品经理啊"/>
<style name="style_flow">
<item name="android:textColor">#fff</item>
<item name="android:padding">10dp</item>
<item name="android:layout_marginLeft">6dp</item>
<item name="android:layout_marginTop">6dp</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:background">@drawable/shpae_circle</item>
<item name="android:layout_height">wrap_content</item>
</style>