2010-06-21 12 views
12

Desidero disporre di una tabella dinamica, con le righe aggiunte nel tempo a seguito dell'interazione dell'utente, utilizzando un TableLayout all'interno di un ScrollView. Funziona bene, ma quando voglio scorrere fino alla fine della tabella usando fullScroll(), lascia sempre fuori l'ultima riga; cioè, scorre in modo tale che l'uno prima dell'ultimo sia visibile. L'ultima riga è visibile quando si scorre manualmente e anche la barra di scorrimento è corretta.Scorrere fino all'ultima riga di TableLayout all'interno di ScrollView

Sono ovviamente aperto a suggerimenti su come ottenere un layout migliore da questo; ma sono specificamente interessato a capire perché fullScroll() si comporta in questo modo. Dovrei dargli un parametro diverso o usare qualcos'altro? O lo fa perché la linea appena aggiunta non è ancora visibile in qualche modo? (se sì, come posso risolverlo?) O mi sono perso qualche altra cosa ovvia?

Il seguente codice repliche il 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> 

Edit: per riferimento, ho implementato Romain Guy 's soluzione come segue:

In TestActivity.java, sostituire:

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

      }); 

che funziona bene.

risposta

15

Nel momento in cui si esegue il fullScroll() il layout non è ancora avvenuto, quindi ScrollView utilizza la "vecchia" dimensione per la tabella. Invece di chiamare fullScroll() subito, usa View.post (Runnable).

+0

Grazie - era una delle cose che sospettavo ma non avevo idea che sarebbe stato così semplice da sistemare. Grazie per avermi aiutato a curare la mia paura di tutto ciò che riguarda i thread :-) – Joubarc

2

Trovare il suggerimento sopra utile, ecco un semplice implementazione che consente di scorrere uno ScrollView per fare un determinato bambino visibile ...

un: Preparare la seguente classe di supporto

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) lo chiamano così

my_scroller.post(new ScrollToTrick(my_scroller,child_to_scroll_to)); 
Problemi correlati