自定义流式布局,只对match_parent、padding进行了处理、子view的margin未进行处理(可通过horizontal_spacing属性处理子view水平间距 ,vertical_spacing处理行间距)
一、基本实现逻辑
1.成员
private float vertical_spacing= 20f; //默认行间距
private float horizontal_spacing = 20f;//默认view间距
2.读取自定义属性,赋值间距
@SuppressLint("CustomViewStyleable")
TypedArray array= context.obtainStyledAttributes(attrs, R.styleable.MyFlowLayout);
horizontal_spacing = array.getDimension(R.styleable.MyFlowLayout_horizontal_spacing, horizontal_spacing);
vertical_spacing = array.getDimension(R.styleable.MyFlowLayout_vertical_spacing, vertical_spacing);
array.recycle();
3.重写onMeasure、onLayout方法
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width= MeasureSpec.getSize(widthMeasureSpec);
int mode_width= MeasureSpec.getMode(widthMeasureSpec);
int currentLineUsedWidth= getPaddingLeft() + getPaddingRight();
int parentViewHeight= getPaddingTop() + getPaddingBottom();
if (mode_width!= MeasureSpec.EXACTLY) {
throw new Error("Pleach set view width_size to Match_parent");
} else {
//由于flowLayout设置最大 只需计算 高度就可
int childSize= getChildCount();
for (int i= 0; i< childSize; i++) {
View view= getChildAt(i);
measureChild(view, widthMeasureSpec, heightMeasureSpec);
if (i== 0) {
parentViewHeight+= view.getMeasuredHeight();
}
if (currentLineUsedWidth!= getPaddingLeft() + getPaddingRight() &&
view.getMeasuredWidth() + horizontal_spacing > width- currentLineUsedWidth) {
currentLineUsedWidth= getPaddingLeft() + getPaddingRight(); //重置下一行宽
parentViewHeight+= view.getMeasuredHeight() + vertical_spacing;
}
if (currentLineUsedWidth!= getPaddingLeft() + getPaddingRight()) {
currentLineUsedWidth+= horizontal_spacing;
}
currentLineUsedWidth+= view.getMeasuredWidth();
}
}
setMeasuredDimension(width, parentViewHeight);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
//定位所有子view的位置 左上右下
int width= getMeasuredWidth();
int lastViewHeight= 0;
int size= getChildCount();
int left= getPaddingLeft();
int top= getPaddingTop();
int right;
int bottom;
for (int i= 0; i< size; i++) {
View view= getChildAt(i);
//定位当前子view位置
int view_height= view.getMeasuredHeight();
int viwe_width= view.getMeasuredWidth();
if (viwe_width+ getPaddingRight() > width- left) {
//换行定位
left= getPaddingLeft();
top+= lastViewHeight+ vertical_spacing;
}
right= left+ viwe_width;
bottom= top+ view_height;
view.layout(left, top, right, bottom);
lastViewHeight= view_height;
left+= viwe_width+ horizontal_spacing; //加上间距
}
}
二、自定义属性
<declare-styleable name ="MyFlowLayout">
<attr name = "vertical_spacing" format ="dimension"/>
<attr name ="horizontal_spacing" format="dimension"/>
</declare-styleable>