TableLayout 整齐堆叠宽度等分布局
2019-12-02 本文已影响0人
kongzue
需求
现有需求,按总宽度N等分,从左往右放置子布局,至最右处换下行继续,整体布局高度按照子布局高度逐级扩张。
Android 自带的 GridLayout 和 TableLayout都不够好用,就自己写了个,原理和StackLabel类似。
代码
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
/**
* Author: @Kongzue
* Github: https://github.com/kongzue/
* Homepage: http://kongzue.com/
* Mail: myzcxhh@live.cn
* CreateTime: 2019/4/24 15:51
*/
public class TableLayout extends ViewGroup {
private int maxColumn = 2;
private int itemMargin = 0;
private int itemHeight = dp2px(150);
private Context context;
public TableLayout(Context context) {
super(context);
this.context = context;
loadAttrs(context, null);
}
public TableLayout(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
loadAttrs(context, attrs);
}
public TableLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
loadAttrs(context, attrs);
}
private void loadAttrs(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.TableLayout);
itemMargin = typedArray.getDimensionPixelOffset(R.styleable.TableLayout_marginDp, 0);
itemHeight = typedArray.getDimensionPixelOffset(R.styleable.TableLayout_itemHeight, dp2px(150));
maxColumn = typedArray.getInteger(R.styleable.TableLayout_column, 2);
typedArray.recycle();
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
}
private List<View> items;
private int newHeight = 0;
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
refreshViews();
setMeasuredDimension(getMeasuredWidth(), newHeight);//设置宽高
}
private void refreshViews() {
int maxWidth = getMeasuredWidth() + itemMargin;
int itemWidth = maxWidth / maxColumn - itemMargin;
items = new ArrayList<>();
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
if (child.getVisibility() == VISIBLE) {
items.add(getChildAt(i));
}
}
newHeight = 0;
if (items != null && !items.isEmpty()) {
int l = 0, t = 0, r = 0, b = 0;
for (int i = 0; i < items.size(); i++) {
View item = items.get(i);
int mWidth = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); //AT_MOST:先按照最大宽度计算,如果小于则按实际值,如果大于,按最大宽度
int mHeight = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); //UNSPECIFIED:不确定,根据实际情况计算
item.measure(mWidth, mHeight);
int childHeight = itemHeight;
if (i != 0 && i % maxColumn == 0) {
l = 0;
t = t + childHeight + itemMargin;
}
r = l + itemWidth;
b = t + childHeight;
item.layout(l, t, r, b);
l = l + itemWidth + itemMargin;
newHeight = t + childHeight;
}
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
private int dp2px(float dpValue) {
return (int) (0.5f + dpValue * Resources.getSystem().getDisplayMetrics().density);
}
}
然后在res/values/新建attr.xml,内容如下
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="TableLayout">
<attr name="marginDp" format="dimension"/>
<attr name="itemHeight" format="dimension"/>
<attr name="column" format="integer"/>
</declare-styleable>
</resources>
简单解释:marginDp 为间距,itemHeight为限制子布局高度值,column为每行几个(N等分)
使用
<yourPackage.TableLayout
android:id="@+id/box_body"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginHorizontal="10dp"
app:itemHeight="100dp"
app:marginDp="10dp">
<!--子布局-->
</yourPackage.TableLayout>
完事儿。