Affichage de liste Faites défiler jusqu'à la fin de la liste après la mise à jour de la liste


292

Je voudrais m'assurer que la liste défile jusqu'en bas, après avoir mis à jour la vue de liste en utilisant listAdapter, afin qu'elle affiche le dernier élément entré dans la liste. Comment puis-je faire ceci ?

J'ai essayé mais pas de chance:

lv.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);

Merci


essayez de faire cela fonctionne ... messagesListView.setTranscriptMode (ListView.TRANSCRIPT_MODE_NORMAL); messagesListView.setStackFromBottom (true);
Superdev

lv.setTranscriptMode (ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL) garantit uniquement que listView défilera vers le bas après avoir appelé adapter.notifyDataSetChanged. Si cela ne fonctionne pas, essayez de définir cette propriété en xml comme vous pouvez le voir dans les articles ci-dessous.
Tomm

Réponses:


418

En supposant que vous sachiez quand les données de la liste ont changé, vous pouvez dire manuellement à la liste de défiler vers le bas en définissant la sélection de liste sur la dernière ligne. Quelque chose comme:

private void scrollMyListViewToBottom() {
    myListView.post(new Runnable() {
        @Override
        public void run() {
            // Select the last row so it will scroll into view...
            myListView.setSelection(myListAdapter.getCount() - 1);
        }
    });
}

@Bhupendra qui n'est pas nécessaire. Vous pouvez également vous passer de fil, comme indiqué dans la réponse de Warting.
sagarpatidar

2
@Bhupendra setSelection () met à jour l'interface utilisateur. En appelant post (Runnable) sur la vue, vous vous assurez que le code Runnable est exécuté sur le thread de l'interface utilisateur Android. Faites-le généralement de cette façon, sauf si vous savez que vous êtes déjà sur le thread d'interface utilisateur ou que vous vous en assurez par d'autres moyens.
Mason Lee

5
il semble également que l'utilisation de la publication sur un adaptateur nouvellement défini provoque une animation de défilement tout en assurant d'être dans le thread principal et que l'utilisation de setSelection immédiatement après la configuration de l'adaptateur ne provoque aucune animation de défilement
Gianluca P.

1
@SaifHamed comme commenté par Mason Lee sur la réponse de Kevin, cela fait également que les listes courtes ont un espace "vide" en haut de la vue au lieu du bas qui n'est probablement pas le comportement prévu.
dashhund

16
vous pouvez également utiliser myListView.smoothScrollToPosition (myListAdapter.getCount () - 1); pour un défilement fluide
Zar E Ahmer

238

Vous devez utiliser ces paramètres dans votre vue de liste:

  • Faire défiler lv.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);

  • Placez la tête de liste en bas lv.setStackFromBottom(true);

Vous pouvez également définir ces paramètres en XML, par exemple. comme ça:

<ListView
   ...
   android:transcriptMode="alwaysScroll"
   android:stackFromBottom="true" />

27
Notez qu'avec cette approche, les lignes «s'empilent du bas» de la vue au fur et à mesure qu'elles sont ajoutées. Cela signifie que les listes restreintes auront un espace "vide" en haut de la vue au lieu du bas, ce qui n'est pas toujours ce que l'on souhaite.
Mason Lee

2
Question rapide: Est-il possible d'animer le défilement? Car actuellement, lorsque je notifie DataSetChanged (), il saute sans animation?!?
Georg

@Georg Avez-vous peut-être désactivé les animations dans les options de développement sur votre appareil?
JonasCz

35

Une combinaison de TRANSCRIPT_MODE_ALWAYS_SCROLL et setSelection l'a fait fonctionner pour moi

ChatAdapter adapter = new ChatAdapter(this);

ListView lv = (ListView) findViewById(R.id.chatList);
lv.setTranscriptMode(AbsListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
lv.setAdapter(adapter);

adapter.registerDataSetObserver(new DataSetObserver() {
    @Override
    public void onChanged() {
        super.onChanged();
        lv.setSelection(adapter.getCount() - 1);    
    }
});

29

J'ai réussi à l'utiliser en réponse à un clic sur un bouton, donc je suppose que vous pouvez également l'utiliser après avoir mis à jour votre contenu:

myListView.smoothScrollToPosition(theListAdapter.getCount() -1);

1
C'est une excellente solution. Simple, une ligne.
Josh Larson

12

Pour obtenir ceci dans un ListFragment:

getListView().setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL); 
getListView().setStackFromBottom(true);`

Ajout de cette réponse parce que si quelqu'un fait une recherche google pour le même problème avec ListFragment, il trouve juste cela ..

Cordialement


9

Utilisation: placez la tête de la liste en bas lv.setStackFromBottom(true);

A fonctionné pour moi et la liste défile automatiquement vers le bas lors de sa première visibilité. La liste défile alors comme il se doit avec TRANSCRIPT_MODE_ALWAYS_SCROLL.


6
Notez qu'avec cette approche, les lignes «s'empilent du bas» de la vue au fur et à mesure qu'elles sont ajoutées. Cela signifie que les listes restreintes auront un espace "vide" en haut de la vue au lieu du bas.
Mason Lee

5

j'utilise

setTranscriptMode(ListView.TRANSCRIPT_MODE_NORMAL);

pour ajouter des entrées en bas, et les anciennes entrées défilent en haut, comme une transcription de chat


Appelez getListView().smoothScrollToPosition(getListAdapter.getCount() - 1);sur place pour faire défiler vers le bas au début de l'activité.
palindrom

4

La solution la plus simple est:

    listView.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
    listView.setStackFromBottom(true);

3

Le mode de transcription est ce que vous voulez et est utilisé par Google Talk et l'application SMS / MMS. Appelez-vous correctement notifyDatasetChanged () sur votre adaptateur lorsque vous ajoutez des éléments?


Oui. la liste est correctement mise à jour, mais commencez toujours par le haut. J'en ai juste besoin pour ajouter le nouvel élément et toujours faire défiler jusqu'à la fin de la liste.
jramirez

Le mode transcription est en fait désactivé par l'application SMS. Je ne me souviens pas pourquoi exactement.
Timmmm
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.