Android onLayout () и AsyncTask () не работают вместе - PullRequest
4 голосов
/ 23 декабря 2011

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

Идея состоит в том, чтобы использовать одну таблицу для заголовка, одну таблицу для содержимого, добавляемого в 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());
        }
    }
}

Приведенный выше код работает отлично (expected), однако, когда я использую 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 () (я проверил это путем создания нескольких журналов), но это не влияет на GUI. Я попытался с помощью invalidate (), forceLayout (), requestLayout (), но ничего не изменилось. wrong

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

Ответы [ 3 ]

2 голосов
/ 27 декабря 2011

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

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

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

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

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

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

1 голос
/ 28 декабря 2011

Я наконец-то узнаю ответ, 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);
    }
}
0 голосов
/ 26 декабря 2011

Ответ заключается в том, что вы должны объявить ваши 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);
        }
    }
}
...