J'ai besoin d'une table déroulante avec en-tête fixe, donc j'ai suivi this great blog et tout va bien.Android onLayout() et AsyncTask() ne fonctionnent pas ensemble
L'idée est d'utiliser une table pour l'en-tête, une table pour le contenu ajouté dans scrollview, les deux sont dans un LinearLayout personnalisé. Dans LinearLayout personnalisé, nous remplacerons le onLayout() pour obtenir la largeur maximale de chaque ligne et définir la largeur pour chaque ligne de l'en-tête et de la table de contenu.
est ici l'activité et sa mise en page:
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>
Activité principale
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());
}
}
}
Cependant, le travail de code ci-dessus parfaitement (), lorsque J'utilise AnysnTask pour obtenir des données du serveur et ajouter des données à la table plus tard, le onLayout() dans mon custo m vue ne fonctionne plus. Je Simuler l'obtention de données par vous déconnecter un certain nombre:
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);
}
}
Ainsi, le OnLayout() ne fonctionnent que quand je l'appelle (appendRows) de thread principal de l'interface utilisateur en le mettant dans la méthode onCreate(). Si j'appelle d'un autre thread UI (dans onPostExecute() de AsyncTask), onLayout() est appelé (je l'ai vérifié en créant des logs) mais cela n'affecte pas l'interface graphique. J'ai essayé avec invalidate(), forceLayout(), requestLayout() mais ne change rien.
Je pense que nous avons besoin d'appeler une méthode pour rafraîchir l'interface graphique mais je ne sais pas ce que c'est, j'ai cherché et essayé beaucoup de façons en 2 jours mais je n'ai rien, donc ce sera très apprécié vous pouvez donner une idée à ce sujet. Merci beaucoup.
Il n'y a pas d'autre "thread" d'interface utilisateur. Le 'onPostExecute' est appelé sur le même thread que' onCreate'. – inazaruk
Si c'est le cas, pourquoi cela fonctionne-t-il quand je mets l'appendRow dans onCreate. – thanhbinh84
Je ne sais pas. Je n'ai pas regardé votre code en profondeur. Mais vous voudrez peut-être penser au problème sans tenir compte des discussions. – inazaruk