我需要一个带有固定标题的可滚动表格,所以我跟着this great blog,一切都很好。
这个想法是使用一个表格作为标题,一个表格用于滚动视图中添加的内容,两者都在自定义的LinearLayout中。在自定义的LinearLayout中,我们将覆盖onLayout()以获取每行的最大宽度,并为header和content表的每一行设置宽度。
以下是活动及其布局:
package com.stylingandroid.ScrollingTable;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TableLayout;
import android.widget.TableRow;
public class ScrollingTable extends LinearLayout
{
public ScrollingTable( Context context )
{
super( context );
}
public ScrollingTable( Context context, AttributeSet attrs )
{
super( context, attrs );
}
@Override
protected void onLayout( boolean changed, int l, int t, int r, int b )
{
super.onLayout( changed, l, t, r, b );
TableLayout header = (TableLayout) findViewById( R.id.HeaderTable );
TableLayout body = (TableLayout) findViewById( R.id.BodyTable );
if (body.getChildCount() > 0 ) {
TableRow bodyRow = (TableRow) body.getChildAt(0);
TableRow headerRow = (TableRow) header.getChildAt(0);
for ( int cellnum = 0; cellnum < bodyRow.getChildCount(); cellnum++ ){
View bodyCell = bodyRow.getChildAt(cellnum);
View headerCell = headerRow.getChildAt(cellnum);
int bodyWidth = bodyCell.getWidth();
int headerWidth = headerCell.getWidth();
int max = Math.max(bodyWidth, headerWidth);
TableRow.LayoutParams bodyParams = (TableRow.LayoutParams)bodyCell.getLayoutParams();
bodyParams.width = max;
TableRow.LayoutParams headerParams = (TableRow.LayoutParams)headerCell.getLayoutParams();
headerParams.width = max;
}
}
}
}
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.stylingandroid.ScrollingTable.ScrollingTable
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent">
<TableLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:id="@+id/HeaderTable">
</TableLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TableLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:id="@+id/BodyTable">
</TableLayout>
</ScrollView>
</com.stylingandroid.ScrollingTable.ScrollingTable>
</LinearLayout>
主要活动
package com.stylingandroid.ScrollingTable;
import android.app.Activity;
import android.app.ProgressDialog;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
public class ScrollingTableActivity extends Activity
{
private String[][] tableData = {
{"header11111111111", "header2","header3","header4"},
{"column1", "column1","column1","column1"},
{"column1", "column1","column1","column1"},
{"column1", "column1","column1","column1"},
{"column1", "column1",
"column1","column1"},
{"column1", "column1","column1","column1"},
{"column1", "column1","column1","column1"},
{"column1", "column1","column1","column1"},
{"column1", "column1","column1","column1"},
{"column1", "column1","column1","column1"},
{"column1", "column1","column1","column1"},
{"column1", "column1","column1","column1"},
{"column1", "column1","column1","column1"}
};
/** Called when the activity is first created. */
@Override
public void onCreate( Bundle savedInstanceState )
{
super.onCreate( savedInstanceState );
setContentView( R.layout.main );
TableLayout tableHeader = (TableLayout)findViewById(R.id.HeaderTable);
TableLayout tableBody = (TableLayout)findViewById(R.id.BodyTable);
appendRows(tableHeader, tableBody, tableData);
}
private void appendRows(TableLayout tableHeader ,TableLayout tableContent, String[][] amortization) {
int rowSize=amortization.length;
int colSize=(amortization.length > 0)?amortization[0].length:0;
for(int i=0; i<rowSize; i++) {
TableRow row1 = new TableRow(this);
for(int j=0; j<colSize; j++) {
TextView c = new TextView(this);
c.setText(amortization[i][j]);
c.setPadding(3, 3, 3, 3);
if (i == 0) {
c.setTextColor(Color.BLACK);
}
row1.addView(c);
}
if (i == 0) {
row1.setBackgroundColor(Color.LTGRAY);
tableHeader.addView(row1, new TableLayout.LayoutParams());
} else {
tableContent.addView(row1, new TableLayout.LayoutParams());
}
}
}
上面的代码完美地工作(),然而,当我使用AnysnTask从服务器获取数据并稍后向表中添加数据时,我的自定义视图中的onLayout()不再起作用。我通过注销一些数字模拟获取数据:
public void onCreate( Bundle savedInstanceState )
{
super.onCreate( savedInstanceState );
setContentView( R.layout.main );
new MyTask().execute();
}
private class MyTask extends AsyncTask<Void, Void, Void> {
private ProgressDialog progressDialog;
protected void onPreExecute() {
progressDialog = ProgressDialog.show(ScrollingTableActivity.this,
"", "Loading. Please wait...", true);
}
@Override
protected Void doInBackground(Void... reportTypes) {
for (int i = 0; i < 500; i++) {
System.out.println(i);
}
return null;
}
@Override
protected void onPostExecute(Void result) {
progressDialog.dismiss();
TableLayout tableHeader = (TableLayout)findViewById(R.id.HeaderTable);
TableLayout tableBody = (TableLayout)findViewById(R.id.BodyTable);
appendRows(tableHeader, tableBody, tableData);
}
}
所以onLayout()只有在我通过将它放在onCreate()方法中从主UI线程调用appendRows()时才有效。如果我从另一个UI线程调用(在AsyncTask的onPostExecute()中),则调用onLayout()(我通过创建一些日志来检查它),但它不会影响GUI。我尝试使用invalidate(),forceLayout(),requestLayout()但不改变任何内容。
我认为我们需要调用一个方法来进行GUI刷新,但不知道它是什么,我已经在2天内搜索并尝试了很多方法但没有得到任何结果,所以如果你能做到,我们将非常感激对此有任何想法。非常感谢。
答案 0 :(得分:2)
您可能想看看这个答案: Android Set textview layout width dynamically
但是,基本上,尝试将每个TextView的宽度设置为与标题相同。
这可能需要你做两次,因为你可能需要让系统进行布局,所以使用View.INVISIBLE
,然后你需要退出AsyncTask,调用另一个,所以布局工作可能会发生。
然后在第二个中,您可以获取不可见的表,循环查找该列中的最大宽度,然后将该列中的所有TextView设置为最大。
这不是最佳解决方案,但应该有效。
我认为您在AsyncTask中的主要问题是需要完成布局,然后才能进行修复。
答案 1 :(得分:1)
我终于找到了答案,setColumnCollapsed()使表格布局刷新,但是我们需要将它放在另一个AsyncTask中,否则它将无法工作,奇怪:(。我把最新的代码放在这里,所以希望它对某人有帮助。此外,这只是解决方法,所以如果有的话,随时发布你的答案......
private class MyTask extends AsyncTask<Void, Void, Void> {
private ProgressDialog progressDialog;
protected void onPreExecute() {
progressDialog = ProgressDialog.show(ScrollingTableActivity.this,
"", "Loading. Please wait...", true);
}
@Override
protected Void doInBackground(Void... reportTypes) {
for (int i = 0; i < 500; i++) {
System.out.println(i);
}
return null;
}
@Override
protected void onPostExecute(Void result) {
progressDialog.dismiss();
appendRows(tableHeader, tableBody, tableData);
new My1Task().execute();
}
}
private class My1Task extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... reportTypes) {
return null;
}
@Override
protected void onPostExecute(Void result) {
tableHeader.setColumnCollapsed(0, false);
tableBody.setColumnCollapsed(0, false);
}
}
答案 2 :(得分:0)
答案是你应该在onCreate()方法之外声明你的TableLayout并在onCreate()中实例化它们。这是解决方案。效果很好。
public class ScrollingTableActivity extends Activity {
TableLayout tableHeader;
TableLayout tableBody;
private String[][] tableData = {
{ "header11111111111", "header2", "header3", "header4" },
{ "column1", "column1", "column1", "column1" },
{ "column1", "column1", "column1", "column1" },
{ "column1", "column1", "column1", "column1" },
{ "column1", "column1", "column1", "column1" } };
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tableHeader = (TableLayout) findViewById(R.id.HeaderTable);
tableBody = (TableLayout) findViewById(R.id.BodyTable);
Log.d("ScrollingTable", "Before appendRows");
//appendRows(tableHeader, tableBody, tableData);
new MyTask().execute();
}
private void appendRows(TableLayout tableHeader, TableLayout tableContent,
String[][] amortization) {
int rowSize = amortization.length;
int colSize = (amortization.length > 0) ? amortization[0].length : 0;
for (int i = 0; i < rowSize; i++) {
TableRow row1 = new TableRow(this);
for (int j = 0; j < colSize; j++) {
TextView c = new TextView(this);
c.setText(amortization[i][j]);
c.setPadding(3, 3, 3, 3);
if (i == 0) {
c.setTextColor(Color.BLACK);
}
row1.addView(c);
}
if (i == 0) {
row1.setBackgroundColor(Color.LTGRAY);
tableHeader.addView(row1, new TableLayout.LayoutParams());
} else {
tableContent.addView(row1, new TableLayout.LayoutParams());
}
}
}
private class MyTask extends AsyncTask<Void, Void, Void> {
private ProgressDialog progressDialog;
protected void onPreExecute() {
progressDialog = ProgressDialog.show(ScrollingTableActivity.this,
"", "Loading. Please wait...", true);
}
@Override
protected Void doInBackground(Void... reportTypes) {
for (int i = 0; i < 500; i++) {
System.out.println(i);
}
return null;
}
@Override
protected void onPostExecute(Void result) {
progressDialog.dismiss();
TableLayout tableHeader = (TableLayout)findViewById(R.id.HeaderTable);
TableLayout tableBody = (TableLayout)findViewById(R.id.BodyTable);
appendRows(tableHeader, tableBody, tableData);
}
}
}