layout.html 表单提交,自定义表格式布局FormLayout

自定义表格式布局FormLayout

项目中有这样的表格式布局,如下图

96d20b4a4e9e

效果图

如果用LinearLayout,RelativeLayout也能实现这样的布局,但是比较麻烦,布局的层级也会比较多。所以就自己自定义了一个FormLayout来展示这些信息。

/**

* 自定义表格布局

*

* author yyw

* date 2017/7/12

* version 1.0

* desc

*/

public class FormLayout extends ViewGroup {

private float[] mChildWeight;//表格的每列的权重,用来计算每列表格的宽度,如果为空表示平均分配

private int columnCount;//表格的总列数

private int rowCount;//表格的总行数

private int dividerSize = 2;//表格边框的宽度

private int[] mChildColumnWidth;//表格每列的宽度

private int[] mChildRowHeight;//表格每行的高度

private Path mDividerPath;//边框的路径

private Paint mDividerPaint;//画笔

public FormLayout(Context context, AttributeSet attrs) {

super(context, attrs);

TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.FormLayout);

CharSequence[] weightArray = array.getTextArray(R.styleable.FormLayout_column_weight_array);

setWeight(weightArray);

columnCount = array.getInt(R.styleable.FormLayout_columnCount, 0);

rowCount = array.getInt(R.styleable.FormLayout_rowCount, 0);

int mDividerColor = array.getColor(R.styleable.FormLayout_dividerColor, Color.BLACK);

dividerSize = array.getDimensionPixelSize(R.styleable.FormLayout_dividerWidth, dividerSize);

array.recycle();

mChildColumnWidth = new int[columnCount];

mChildRowHeight = new int[rowCount];

mDividerPath = new Path();

mDividerPaint = new Paint();

mDividerPaint.setColor(mDividerColor);

mDividerPaint.setAntiAlias(true);

mDividerPaint.setStrokeWidth(dividerSize);

mDividerPaint.setStyle(Paint.Style.STROKE);

setWillNotDraw(false);

}

private void setWeight(CharSequence[] weightArray) {

if (weightArray == null) return;

mChildWeight = new float[weightArray.length];

for (int i = 0; i < weightArray.length; i++) {

float w = Float.parseFloat(weightArray[i].toString().trim());

mChildWeight[i] = w;

}

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

if (columnCount == 0 || rowCount == 0) return;

int widthSize = MeasureSpec.getSize(widthMeasureSpec);

//计算每列的宽度

fillChildWidth(widthSize);

for (int i = 0; i < mChildRowHeight.length; i++) {

//计算每行的高度

mChildRowHeight[i] = getChildAtRowMaxHeight(i);

}

final int childCount = getChildCount();

for (int i = 0; i < childCount; i++) {

View child = getChildAt(i);

LayoutParams params = (LayoutParams) child.getLayoutParams();

//计算总的宽度

int childWidth = 0;

for (int j = params.columnIndex; j < (params.columnCount + params.columnIndex); j++) {

childWidth += mChildColumnWidth[j];

}

childWidth += (params.columnCount - 1) * dividerSize;

//计算总的高度

int childHeight = 0;

for (int j = params.rowIndex; j < (params.rowIndex + params.rowCount); j++) {

childHeight += mChildRowHeight[j];

}

childHeight += (params.rowCount - 1) * dividerSize;

int childWidthMeasureSpec = getChildMeasureSpec(MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY),

getPaddingLeft() + getPaddingRight() + params.leftMargin

+ params.rightMargin, childWidth);

int childHeightMeasureSpec = getChildMeasureSpec(MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY),

getPaddingTop() + getPaddingBottom() + params.topMargin

+ params.bottomMargin, childHeight);

child.measure(childWidthMeasureSpec, childHeightMeasureSpec);

}

//计算布局的总高度

int allHeight = 0;

for (int h : mChildRowHeight) {

allHeight += h;

}

allHeight += (rowCount + 1) * dividerSize;

allHeight += getPaddingBottom() + getPaddingTop();

super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(allHeight, MeasureSpec.EXACTLY));

}

/**

* 获取每行的最大的高度

*

* @param row 行数

* @return 最大高度

*/

private int getChildAtRowMaxHeight(int row) {

final int childCount = getChildCount();

int maxHeight = 0;

for (int i = 0; i < childCount; i++) {

View child = getChildAt(i);

LayoutParams params = (LayoutParams) child.getLayoutParams();

if (row >= params.rowIndex && row < (params.rowIndex + params.rowCount)) {//表示在获取范围内

int childWidth = 0;

for (int j = params.columnIndex; j < (params.columnCount + params.columnIndex); j++) {

childWidth += mChildColumnWidth[j];//计算所占列的总宽度

}

childWidth += (params.columnCount - 1) * dividerSize;//计算总的宽度

int childHeight = getChildMeasureHeight(child, params, childWidth);

int rowHeight = (childHeight - (params.rowCount - 1) * dividerSize) / params.rowCount;//把宽度分给所占行的高度

maxHeight = Math.max(maxHeight, rowHeight);

}

}

return maxHeight;

}

/**

* 获取行高

*

* @param child 子view

* @param lp 子view的LayoutParams

* @param childWidth 子view的宽度

* @return 获取子view的高度

*/

private int getChildMeasureHeight(View child, LayoutParams lp, int childWidth) {

int childWidthMeasureSpec = getChildMeasureSpec(MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY),

getPaddingLeft() + getPaddingRight() + lp.leftMargin

+ lp.rightMargin, childWidth);

int childHeightMeasureSpec = getChildMeasureSpec(MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.UNSPECIFIED),

getPaddingTop() + getPaddingBottom() + lp.topMargin

+ lp.bottomMargin, ViewGroup.LayoutParams.WRAP_CONTENT);

child.measure(childWidthMeasureSpec, childHeightMeasureSpec);

return child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;

}

/**

* 计算每列的位置

*

* @param widthSize 宽度

*/

private void fillChildWidth(int widthSize) {

int paddingLeft = getPaddingLeft();

int paddingRight = getPaddingRight();

widthSize = widthSize - paddingLeft - paddingRight - (columnCount + 1) * dividerSize;

if (mChildWeight != null && mChildWeight.length == mChildColumnWidth.length) {

float allWeight = 0.0f;

for (float w : mChildWeight) {

allWeight += w;

}

float weightStep = widthSize / allWeight;

for (int i = 0; i < mChildWeight.length; i++) {

mChildColumnWidth[i] = Math.round(mChildWeight[i] * weightStep);

}

} else {

float weightStep = widthSize / mChildColumnWidth.length;

for (int i = 0; i < mChildColumnWidth.length; i++) {

mChildColumnWidth[i] = Math.round(weightStep);

}

}

}

@Override

protected void onLayout(boolean changed, int left, int top, int right, int bottom) {

final int childTop = getPaddingTop() + dividerSize;

final int childLeft = getPaddingLeft() + dividerSize;

final int count = getChildCount();

for (int i = 0; i < count; i++) {

View child = getChildAt(i);

LayoutParams params = (LayoutParams) child.getLayoutParams();

int t = getCurrentTop(childTop, params.rowIndex) + params.rowIndex * dividerSize;

int l = getCurrentLeft(childLeft, params.columnIndex) + params.columnIndex * dividerSize;

int b = t + child.getMeasuredHeight();

int r = l + child.getMeasuredWidth();

child.layout(l, t, r, b);

}

}

private int getCurrentTop(int childTop, int rowIndex) {

for (int i = 0; i < rowIndex; i++) {

childTop += mChildRowHeight[i];

}

return childTop;

}

private int getCurrentLeft(int childLeft, int columnIndex) {

for (int i = 0; i < columnIndex; i++) {

childLeft += mChildColumnWidth[i];

}

return childLeft;

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

//画边框

mDividerPath.reset();

final int childCount = getChildCount();

final int halfSize = dividerSize / 2;

for (int i = 0; i < childCount; i++) {

View child = getChildAt(i);

mDividerPath.moveTo(child.getLeft() - halfSize, child.getTop() - halfSize);

mDividerPath.lineTo(child.getLeft() - halfSize, child.getBottom() + halfSize);

mDividerPath.lineTo(child.getRight() + halfSize, child.getBottom() + halfSize);

mDividerPath.lineTo(child.getRight() + halfSize, child.getTop() - halfSize);

mDividerPath.lineTo(child.getLeft() - halfSize, child.getTop() - halfSize);

}

canvas.drawPath(mDividerPath, mDividerPaint);

}

@Override

protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {

return p instanceof LayoutParams;

}

@Override

public LayoutParams generateLayoutParams(AttributeSet attrs) {

return new LayoutParams(getContext(), attrs);

}

@Override

protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {

return new LayoutParams(p);

}

/**

* Per child parameters for children views of the {@link FormLayout}.

*/

public static class LayoutParams extends ViewGroup.MarginLayoutParams {

public int rowIndex;

public int rowCount;

public int columnIndex;

public int columnCount;

public LayoutParams(Context c, AttributeSet attrs) {

super(c, attrs);

TypedArray array = c.obtainStyledAttributes(attrs, R.styleable.FormLayout_Layout);

rowIndex = array.getInt(R.styleable.FormLayout_Layout_layout_rowIndex, 0);

rowCount = array.getInt(R.styleable.FormLayout_Layout_layout_rowCount, 1);

columnIndex = array.getInt(R.styleable.FormLayout_Layout_layout_columnIndex, 0);

columnCount = array.getInt(R.styleable.FormLayout_Layout_layout_columnCount, 1);

array.recycle();

}

public LayoutParams(@Px int width, @Px int height) {

super(new ViewGroup.LayoutParams(width, height));

}

public LayoutParams(LayoutParams source) {

super(source);

rowIndex = source.rowIndex;

rowCount = source.rowCount;

columnIndex = source.columnIndex;

columnCount = source.columnCount;

}

public LayoutParams(ViewGroup.LayoutParams source) {

super(source);

}

}

}

自定义属性

Demo

96d20b4a4e9e

效果图

代码布局:

android:layout_width="match_parent"

android:layout_height="wrap_content"

app:columnCount="3"

app:rowCount="3">

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:gravity="center"

android:padding="10dp"

android:text="占一列三行"

app:layout_columnIndex="0"

app:layout_rowCount="3"

app:layout_rowIndex="0"/>

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:gravity="center"

android:padding="10dp"

android:text="占两列一行"

app:layout_columnCount="2"

app:layout_columnIndex="1"

app:layout_rowIndex="0"/>

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:gravity="center"

android:padding="10dp"

android:text="占一列一行"

app:layout_columnIndex="1"

app:layout_rowIndex="1"/>

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:gravity="center"

android:padding="10dp"

android:text="占一列一行"

app:layout_columnIndex="1"

app:layout_rowIndex="2"/>

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:gravity="center"

android:padding="10dp"

android:text="占一列两行"

app:layout_columnIndex="2"

app:layout_rowCount="2"

app:layout_rowIndex="1"/>

如果要改动每列的宽度权重

可以定义一个String数组

1

1.5

2

在布局中加入

app:column_weight_array="@array/demo"

效果图

96d20b4a4e9e

效果图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值