2010-06-21 10 views
12

Ich möchte eine dynamische Tabelle mit Zeilen im Laufe der Zeit als Ergebnis der Benutzerinteraktion mit einer TableLayout innerhalb einer ScrollView haben. Das funktioniert gut, aber wenn ich mit fullScroll() zum Ende der Tabelle scrollen möchte, wird immer die letzte Zeile weggelassen; das heißt, es scrollt so, dass der eine vor dem letzten sichtbar ist. Die letzte Zeile ist beim manuellen Scrollen sichtbar und die Bildlaufleiste ist auch korrekt.Scrollen zur letzten Zeile von TableLayout innerhalb einer ScrollView

Ich bin natürlich offen für Vorschläge, wie man ein besseres Layout daraus machen kann; aber ich bin speziell daran interessiert zu verstehen, warum fullScroll() sich so verhält. Soll ich einen anderen Parameter angeben oder etwas ganz anderes verwenden? Oder macht es das, weil die neu hinzugefügte Zeile noch nicht sichtbar ist? (Wenn ja, wie kann ich das lösen?) Oder habe ich eine andere offensichtliche Sache vermisst?

Der folgende Code repliziert das Problem:

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> 

Edit: als Referenz, ich Romain Guy ‚s umgesetzt Lösung wie folgt:

In TestActivity.java ersetzen:

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

mit:

  // 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); 
       } 

      }); 

der gut arbeitet.

Antwort

15

Zu der Zeit, als Sie fullScroll() ausgeführt haben, ist das Layout noch nicht passiert, also verwendet die ScrollView die "alte" Größe für die Tabelle. Anstatt fullScroll() sofort aufzurufen, verwenden Sie View.post (Runnable).

+0

Danke - es war eines der Dinge, die ich vermutete, aber hatte keine echte Idee, es wäre so einfach zu beheben. Danke, dass du mir geholfen hast, meine Angst vor allem Thread-bezogenen zu heilen :-) – Joubarc

2

den Hinweis oben nützlich zu finden, hier ist eine einfache Implementierung, die einen Scroll scrollt ein bestimmtes Kind sichtbar zu machen ...

a: es Bereiten Sie die folgende Hilfsklasse

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) nennen wie dieses