Android onLayout () и AsyncTask () не работают вместе

Мне нужна прокручиваемая таблица с фиксированным заголовком, поэтому я следил за этим замечательным блогом, и все в порядке.

Идея заключается в использовании одной таблицы для заголовка, одной таблицы для контента, добавленной в scrollview, оба из которых находятся в настраиваемом LinearLayout. В индивидуальном LinearLayout мы перезапишем onLayout (), чтобы получить максимальную ширину каждой строки и задать ширину для каждой строки как таблицы заголовка, так и содержимого.

Вот деятельность и ее макет:

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 () работает только тогда, когда я вызываю appendRows () из основного потока пользовательского интерфейса, помещая его в метод onCreate (). Если я вызываю из другого потока пользовательского интерфейса (в onPostExecute () AsyncTask), вызывается onLayout () (я проверил его, создав несколько журналов), но это не влияет на графический интерфейс. Я пытался с invalidate (), forceLayout (), requestLayout (), но ничего не менял. неправильно

Я думаю, нам нужно вызвать метод, чтобы обновить GUI, но не знаю, что это такое, я искал и пробовал много способов за 2 дня, но ничего не получил, поэтому будет очень признателен, если вы сможете дать какую-либо идею об этом. Большое спасибо.

Вы можете посмотреть на этот ответ: Android Установить ширину раскладки текстового вида динамически

Но, в основном, попробуйте установить ширину каждого TextView таким же, как и заголовок.

Это может потребовать, чтобы вы делали все дважды, так как вам, вероятно, потребуется, чтобы система выполняла макет, поэтому используйте View.INVISIBLE , тогда вам нужно будет выйти из AsyncTask, вызвав другую, чтобы работа макета могла произойти.

Затем во втором вы можете получить невидимые таблицы, пропустить их, чтобы найти наибольшую ширину в этом столбце, а затем установить все текстовые элементы в этом столбце на самый большой.

Это не лучшее решение, но оно должно работать.

Я думаю, что ваша основная проблема в AsyncTask заключается в том, что макет должен быть выполнен, тогда вы можете сделать исправление.

Я, наконец, узнаю ответ, 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); } } 

Ответ заключается в том, что вы должны объявить свой метод TableLayouts вне метода onCreate () и создать экземпляр в 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); } } } 
Intereting Posts
Как я могу просто загрузить изображение с универсальным загрузчиком изображений Наложение фрагмента на другой фрагмент Выбор изображения из галереи с использованием фрагмента ActionBar с настраиваемой компоновкой с настраиваемым пунктом меню Как получить текущий год в Android? Получение аббревиатуры государства от getAdminArea (); Добавление OnItemSelectedListener в Spinner Совместное использование временных файлов между приложениями без SD-карты Общие указатели: есть ли какие-либо отличия между шаблоном «sp <>» для Android и шаблоном «shared_ptr <>» от BOOST? Странная ошибка в R.java, даже после очистки проекта: «Подчеркивания могут использоваться только с уровнем 1,7 или выше» Включить изменение ориентации дисплея, когда определенные фрагменты видны и отключены, когда другие Android geofencing, когда приложение убито Есть ли у Glide метод загрузки PNG и SVG? Facebook на Android: целевое приложение не открывается при нажатии на ссылку RequestLocationUpdates () в отдельной теме