2010-06-21 12 views
12

Quiero tener una tabla dinámica, con filas añadieron con el tiempo como resultado de la interacción del usuario, utilizando un TableLayout dentro de un ScrollView. Esto funciona bien, pero cuando quiero para desplazarse hasta el extremo de la mesa usando fullScroll(), siempre deja fuera la última línea; es decir, se desplaza para que el anterior al último sea visible. La última línea es visible cuando se desplaza manualmente, y la barra de desplazamiento también es correcta.Desplazarse a la última línea de TableLayout dentro de un ScrollView

estoy, por supuesto, abierto a sugerencias en cuanto a cómo hacer un mejor diseño fuera de este; pero estoy específicamente interesado en entender por qué fullScroll() se comporta de esa manera. ¿Debo darle un parámetro diferente, o usar algo completamente distinto? ¿O lo hace porque la línea recién agregada aún no está visible de alguna manera? (De ser así, ¿cómo puedo resolver eso?) ¿O me perdí alguna otra cosa obvia?

El siguiente código se replica el problema:

TestActivity.java:

package com.example.android.tests; 

import java.util.Random; 
import android.app.Activity; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.Button; 
import android.widget.ScrollView; 
import android.widget.TableLayout; 
import android.widget.TableRow; 
import android.widget.TextView; 

public class TestActivity extends Activity { 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     ((Button) findViewById(R.id.AddRow)).setOnClickListener(new View.OnClickListener() { 
      public void onClick(View v) { 
       Random rnd = new Random(); 
       TableRow nr = new TableRow(v.getContext()); 
       for (int c=0; c<3; c++) { 
        TextView nv = new TextView(v.getContext()); 
        nv.setText(Integer.toString(rnd.nextInt(20)-10)); 
        nr.addView(nv); 
       } 
       ((TableLayout) findViewById(R.id.Table)).addView(nr); 
       // Scrolls to line before last - why? 
       ((ScrollView) findViewById(R.id.TableScroller)).fullScroll(View.FOCUS_DOWN); 
      } 
     }); 

    } 
} 

Main.xml:

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent"> 
    <Button 
    android:text="Add Row" 
    android:id="@+id/AddRow" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:layout_alignParentBottom="true" /> 
    <ScrollView 
    android:id="@+id/TableScroller" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:layout_above="@id/AddRow" 
    android:layout_alignParentTop="true" > 
    <TableLayout 
     android:id="@+id/Table" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:stretchColumns="0,1,2" /> 
    </ScrollView> 
</RelativeLayout> 

Editar: para referencia, he implementado Romain Guy 's solución como sigue:

En TestActivity.java, reemplace:

  // Scrolls to line before last - why? 
      ((ScrollView) findViewById(R.id.TableScroller)).fullScroll(View.FOCUS_DOWN); 

con:

  // Enqueue the scrolling to happen after the new row has been layout 
      ((ScrollView) findViewById(R.id.TableScroller)).post(new Runnable() { 
       public void run() { 
        ((ScrollView) findViewById(R.id.TableScroller)).fullScroll(View.FOCUS_DOWN); 
       } 

      }); 

que funciona muy bien.

Respuesta

15

En el momento que está haciendo su fullScroll() el diseño aún no ha sucedido, por lo que el ScrollView utiliza el tamaño de la "vieja" de la tabla. En lugar de llamar a fullScroll() de inmediato, use View.post (Runnable).

+0

Gracias - era una de las cosas que sospechaba, pero no tenía idea de que sería tan fácil de arreglar. Gracias por ayudarme a curar mi miedo a todo lo relacionado con los hilos :-) – Joubarc

2

Encontrar la sugerencia anterior útil, aquí es una sencilla aplicación que se desplaza un ScrollView para hacer un niño dado visibles ...

a: Preparar la siguiente clase de ayuda

public class ScrollToTrick implements Runnable { 

ScrollView scroller; 
View  child; 

ScrollToTrick(ScrollView scroller, View child) { 
    this.scroller=scroller; 
    this.child=child; 

} 
public void run() { 
    scroller.scrollTo(0, child.getTop()); 
} 
} 

b) llamarlo como este

my_scroller.post(new ScrollToTrick(my_scroller,child_to_scroll_to)); 
Cuestiones relacionadas