如何在运行时使用自定义(水平和垂直)分隔线创建动态 TableLayout
How to create dynamic TableLayout in runtime with custom (horizontal and vertical) dividers
基本上我想创建一个函数,它动态创建一个带有水平和垂直自定义分隔线的 TableLayout,我将其插入到 FrameLayout(容器)中。我可以在 XML 中轻松做到这一点,但我需要在运行时做到这一点,主要是因为我不知道 table 会有多大,也可能很大(想避免复制+粘贴代码XML 多次)。
这正是我想要的(静态的),但在 XML:
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/unitsTableContainer"
android:layout_margin="30dp">
<View style="@style/TableVerticalDivider"/>
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View style="@style/TableHorizontalDivider"/>
<TextView style="@style/UnitTableDefaultText"/>
<View style="@style/TableHorizontalDivider"/>
<TextView style="@style/UnitTableDefaultText"/>
<View style="@style/TableHorizontalDivider"/>
<TextView style="@style/UnitTableDefaultText"/>
<View style="@style/TableHorizontalDivider"/>
<TextView style="@style/UnitTableDefaultText"/>
<View style="@style/TableHorizontalDivider"/>
</TableRow>
<View style="@style/TableVerticalDivider"/>
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View style="@style/TableHorizontalDivider"/>
<TextView style="@style/UnitTableDefaultText"/>
<View style="@style/TableHorizontalDivider"/>
<TextView style="@style/UnitTableDefaultText"/>
<View style="@style/TableHorizontalDivider"/>
<TextView style="@style/UnitTableDefaultText"/>
<View style="@style/TableHorizontalDivider"/>
<TextView style="@style/UnitTableDefaultText"/>
<View style="@style/TableHorizontalDivider"/>
</TableRow>
<View style="@style/TableVerticalDivider"/>
</TableLayout>
这是我在运行时(动态)的最佳结果:
private void createTable() {
TableLayout tableLayout;
View verticalTableColumnDivider;
View horizontalTableRowDivider;
TableRow tableRow;
TextView textView;
tableLayout = new TableLayout(getApplicationContext());
tableLayout.setStretchAllColumns(true);
for (int currentRow = 0; currentRow < 2; currentRow++) {
tableRow = new TableRow(getApplicationContext());
verticalTableColumnDivider = getLayoutInflater().inflate(R.layout.template_vertical_table_divider, null);
horizontalTableRowDivider = getLayoutInflater().inflate(R.layout.template_horizontal_table_divider, null);
tableRow.addView(horizontalTableRowDivider);
for (int currentColumn = 0; currentColumn < 4; currentColumn++) {
textView = (TextView) getLayoutInflater().inflate(R.layout.template_default_table_text, null);
tableRow.addView(textView);
horizontalTableRowDivider = getLayoutInflater().inflate(R.layout.template_horizontal_table_divider, null);
tableRow.addView(horizontalTableRowDivider);
}
tableLayout.addView(verticalTableColumnDivider);
tableLayout.addView(tableRow);
}
verticalTableColumnDivider = getLayoutInflater().inflate(R.layout.template_vertical_table_divider, null);
tableLayout.addView(verticalTableColumnDivider);
FrameLayout tableLayoutContainer = (FrameLayout) findViewById(R.id.unitsTableContainer);
tableLayoutContainer.addView(tableLayout);
}
这是模板及其样式(当然样式在一个 XML 文件中,所有 3 个模板在单独的布局 XML 文件中):
<View style="@style/TableHorizontalDivider"/>
<style name="TableHorizontalDivider">
<item name="android:layout_width">4dp</item>
<item name="android:layout_height">match_parent</item>
<item name="android:background">?android:attr/listDivider</item>
<item name="android:visibility">visible</item>
</style>
<View style="@style/TableVerticalDivider"/>
<style name="TableVerticalDivider">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">4dp</item>
<item name="android:background">?android:attr/listDivider</item>
<item name="android:visibility">visible</item>
</style>
<TextView style="@style/UnitTableDefaultText"/>
<style name="UnitTableDefaultText">
<item name="android:textColor">#222222</item>
<item name="android:text">Test</item>
<item name="android:textSize">16sp</item>
<item name="android:gravity">center</item>
<item name="android:layout_gravity">center</item>
<item name="android:layout_weight">1</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_width">0dp</item>
</style>
这是结果,top table 是动态生成的,bottom table 应该是静态生成的:
result of my tries
将textViews放入TableLayout没有问题,因为你可以看到只有分隔符有问题,行分隔符太细,列分隔符(如果你仔细看)它们也太细并且堆叠在行分隔符上,不知道为什么它们是水平绘制而不是垂直绘制的。因此,如果有人知道为什么分隔线画错了,和/或有不同的解决方法,请告诉我。
好的,我知道怎么做了。我制作了一个 class,您将文本内容作为 table 的 String[][],它会在运行时创建 table:
public class SimpleTextTableWithBorders extends TableLayout {
private Context mContext;
private String[][] mTableContent;
private int mTextColor, mBorderColor;
private int mTextViewBorderWidth, mTableBorderWidth;
public SimpleTextTableWithBorders(Context context, String[][] tableContent) {
super(context);
mContext = context;
mTableContent = tableContent;
mTextColor = 0xff111111;
mBorderColor = 0xAA444444;
mTextViewBorderWidth = 4;
mTableBorderWidth = mTextViewBorderWidth * 2;
setupTable();
}
private void setupTable() {
TableRow tableRow;
TextView textView;
setStretchAllColumns(true);
setBackground(borderDrawable(mTableBorderWidth));
setPadding(mTableBorderWidth, mTableBorderWidth, mTableBorderWidth, mTableBorderWidth);
for (int currentRow = 0; currentRow < mTableContent.length; currentRow++) {
tableRow = new TableRow(mContext);
for (int currentColumn = 0; currentColumn < mTableContent[0].length; currentColumn++) {
textView = new TextView(mContext);
textView.setTextColor(mTextColor);
textView.setBackground(borderDrawable(mTextViewBorderWidth));
textView.setText(mTableContent[currentRow][currentColumn]);
textView.setGravity(Gravity.CENTER);
textView.setPadding(0, 6, 0, 6);
tableRow.addView(textView);
}
addView(tableRow);
}
}
private GradientDrawable borderDrawable(int borderWidth) {
GradientDrawable shapeDrawable = new GradientDrawable();
shapeDrawable.setStroke(borderWidth, mBorderColor);
return shapeDrawable;
}
}
我一直在寻找的关键是 GradientDrawable。没有 setter 和 getter,但是如果有人需要,你可以把它和其他有用的方法一起放在那里,你想用就用。
示例结果如下:
基本上我想创建一个函数,它动态创建一个带有水平和垂直自定义分隔线的 TableLayout,我将其插入到 FrameLayout(容器)中。我可以在 XML 中轻松做到这一点,但我需要在运行时做到这一点,主要是因为我不知道 table 会有多大,也可能很大(想避免复制+粘贴代码XML 多次)。
这正是我想要的(静态的),但在 XML:
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/unitsTableContainer"
android:layout_margin="30dp">
<View style="@style/TableVerticalDivider"/>
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View style="@style/TableHorizontalDivider"/>
<TextView style="@style/UnitTableDefaultText"/>
<View style="@style/TableHorizontalDivider"/>
<TextView style="@style/UnitTableDefaultText"/>
<View style="@style/TableHorizontalDivider"/>
<TextView style="@style/UnitTableDefaultText"/>
<View style="@style/TableHorizontalDivider"/>
<TextView style="@style/UnitTableDefaultText"/>
<View style="@style/TableHorizontalDivider"/>
</TableRow>
<View style="@style/TableVerticalDivider"/>
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View style="@style/TableHorizontalDivider"/>
<TextView style="@style/UnitTableDefaultText"/>
<View style="@style/TableHorizontalDivider"/>
<TextView style="@style/UnitTableDefaultText"/>
<View style="@style/TableHorizontalDivider"/>
<TextView style="@style/UnitTableDefaultText"/>
<View style="@style/TableHorizontalDivider"/>
<TextView style="@style/UnitTableDefaultText"/>
<View style="@style/TableHorizontalDivider"/>
</TableRow>
<View style="@style/TableVerticalDivider"/>
</TableLayout>
这是我在运行时(动态)的最佳结果:
private void createTable() {
TableLayout tableLayout;
View verticalTableColumnDivider;
View horizontalTableRowDivider;
TableRow tableRow;
TextView textView;
tableLayout = new TableLayout(getApplicationContext());
tableLayout.setStretchAllColumns(true);
for (int currentRow = 0; currentRow < 2; currentRow++) {
tableRow = new TableRow(getApplicationContext());
verticalTableColumnDivider = getLayoutInflater().inflate(R.layout.template_vertical_table_divider, null);
horizontalTableRowDivider = getLayoutInflater().inflate(R.layout.template_horizontal_table_divider, null);
tableRow.addView(horizontalTableRowDivider);
for (int currentColumn = 0; currentColumn < 4; currentColumn++) {
textView = (TextView) getLayoutInflater().inflate(R.layout.template_default_table_text, null);
tableRow.addView(textView);
horizontalTableRowDivider = getLayoutInflater().inflate(R.layout.template_horizontal_table_divider, null);
tableRow.addView(horizontalTableRowDivider);
}
tableLayout.addView(verticalTableColumnDivider);
tableLayout.addView(tableRow);
}
verticalTableColumnDivider = getLayoutInflater().inflate(R.layout.template_vertical_table_divider, null);
tableLayout.addView(verticalTableColumnDivider);
FrameLayout tableLayoutContainer = (FrameLayout) findViewById(R.id.unitsTableContainer);
tableLayoutContainer.addView(tableLayout);
}
这是模板及其样式(当然样式在一个 XML 文件中,所有 3 个模板在单独的布局 XML 文件中):
<View style="@style/TableHorizontalDivider"/>
<style name="TableHorizontalDivider">
<item name="android:layout_width">4dp</item>
<item name="android:layout_height">match_parent</item>
<item name="android:background">?android:attr/listDivider</item>
<item name="android:visibility">visible</item>
</style>
<View style="@style/TableVerticalDivider"/>
<style name="TableVerticalDivider">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">4dp</item>
<item name="android:background">?android:attr/listDivider</item>
<item name="android:visibility">visible</item>
</style>
<TextView style="@style/UnitTableDefaultText"/>
<style name="UnitTableDefaultText">
<item name="android:textColor">#222222</item>
<item name="android:text">Test</item>
<item name="android:textSize">16sp</item>
<item name="android:gravity">center</item>
<item name="android:layout_gravity">center</item>
<item name="android:layout_weight">1</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_width">0dp</item>
</style>
这是结果,top table 是动态生成的,bottom table 应该是静态生成的: result of my tries
将textViews放入TableLayout没有问题,因为你可以看到只有分隔符有问题,行分隔符太细,列分隔符(如果你仔细看)它们也太细并且堆叠在行分隔符上,不知道为什么它们是水平绘制而不是垂直绘制的。因此,如果有人知道为什么分隔线画错了,和/或有不同的解决方法,请告诉我。
好的,我知道怎么做了。我制作了一个 class,您将文本内容作为 table 的 String[][],它会在运行时创建 table:
public class SimpleTextTableWithBorders extends TableLayout {
private Context mContext;
private String[][] mTableContent;
private int mTextColor, mBorderColor;
private int mTextViewBorderWidth, mTableBorderWidth;
public SimpleTextTableWithBorders(Context context, String[][] tableContent) {
super(context);
mContext = context;
mTableContent = tableContent;
mTextColor = 0xff111111;
mBorderColor = 0xAA444444;
mTextViewBorderWidth = 4;
mTableBorderWidth = mTextViewBorderWidth * 2;
setupTable();
}
private void setupTable() {
TableRow tableRow;
TextView textView;
setStretchAllColumns(true);
setBackground(borderDrawable(mTableBorderWidth));
setPadding(mTableBorderWidth, mTableBorderWidth, mTableBorderWidth, mTableBorderWidth);
for (int currentRow = 0; currentRow < mTableContent.length; currentRow++) {
tableRow = new TableRow(mContext);
for (int currentColumn = 0; currentColumn < mTableContent[0].length; currentColumn++) {
textView = new TextView(mContext);
textView.setTextColor(mTextColor);
textView.setBackground(borderDrawable(mTextViewBorderWidth));
textView.setText(mTableContent[currentRow][currentColumn]);
textView.setGravity(Gravity.CENTER);
textView.setPadding(0, 6, 0, 6);
tableRow.addView(textView);
}
addView(tableRow);
}
}
private GradientDrawable borderDrawable(int borderWidth) {
GradientDrawable shapeDrawable = new GradientDrawable();
shapeDrawable.setStroke(borderWidth, mBorderColor);
return shapeDrawable;
}
}
我一直在寻找的关键是 GradientDrawable。没有 setter 和 getter,但是如果有人需要,你可以把它和其他有用的方法一起放在那里,你想用就用。
示例结果如下: