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>

完事儿。

上一篇下一篇

猜你喜欢

热点阅读