106 votes

Déterminer si le ListView est déroulé jusqu'en bas ?

Puis-je savoir si mon ListView est déroulé jusqu'en bas ? J'entends par là que le dernier élément est entièrement visible.

171voto

Wroclai Points 15042

Modifié :

Comme j'ai étudié ce sujet particulier dans l'une de mes applications, je peux écrire une réponse détaillée pour les futurs lecteurs de cette question.

Mettre en œuvre un OnScrollListener , définissez votre ListView 's onScrollListener et alors vous devriez être capable de gérer les choses correctement.

Par exemple :

private int preLast;
// Initialization stuff.
yourListView.setOnScrollListener(this);

// ... ... ...

@Override
public void onScroll(AbsListView lw, final int firstVisibleItem,
        final int visibleItemCount, final int totalItemCount)
{

    switch(lw.getId()) 
    {
        case R.id.your_list_id:     

            // Make your calculation stuff here. You have all your
            // needed info from the parameters of this function.

            // Sample calculation to determine if the last 
            // item is fully visible.
            final int lastItem = firstVisibleItem + visibleItemCount;

            if(lastItem == totalItemCount)
            {
                if(preLast!=lastItem)
                {
                    //to avoid multiple calls for last item
                    Log.d("Last", "Last");
                    preLast = lastItem;
                }
            }
    }
}

26 votes

Cela ne permettra pas de détecter si le dernier élément est entièrement visible.

1 votes

Si vous avez des en-têtes ou des pieds de page dans votre liste, vous devez également en tenir compte.

5 votes

@Wroclai Cela ne permettra pas de détecter si le dernier élément est entièrement visible.

68voto

Martijn Points 296

Réponse tardive, mais si vous souhaitez simplement vérifier si votre ListView a défilé jusqu'en bas ou non, sans créer un écouteur d'événement, vous pouvez utiliser cette instruction if :

if (yourListView.getLastVisiblePosition() == yourListView.getAdapter().getCount() -1 &&
    yourListView.getChildAt(yourListView.getChildCount() - 1).getBottom() <= yourListView.getHeight())
{
    //It is scrolled all the way down here

}

Il vérifie d'abord si la dernière position possible est en vue. Ensuite, il vérifie si le bas du dernier bouton s'aligne sur le bas de la ListView. Vous pouvez faire quelque chose de similaire pour savoir s'il est tout en haut :

if (yourListView.getFirstVisiblePosition() == 0 &&
    yourListView.getChildAt(0).getTop() >= 0)
{
    //It is scrolled all the way up here

}

4 votes

Merci. Il faut juste changer ...getChildAt(yourListView.getCount() -1)... en ...getChildAt(yourListView.getChildCount() -1)...

0 votes

@OferR Pas sûr, mais je pense que getChildCount() renvoie les vues dans le groupe de vues, ce qui, avec le recyclage des vues, n'est pas le même que le nombre d'éléments dans l'adaptateur. Cependant, puisque ListView descend de AdapterView, vous pouvez utiliser getCount() directement sur le ListView.

0 votes

William T. Mallard Votre première phrase est correcte, et c'est exactement ce que nous voulons : La dernière vue affichée dans le groupe. Cela permet de vérifier qu'elle est entièrement visible. (Considérez une ListView avec 20 lignes, mais seulement les 8 dernières sont affichées. Nous voulons obtenir la 8ème vue dans le ViewGroup, pas la 20ème qui n'existe pas).

10voto

Chris Stewart Points 1862

Quelque chose comme ça :

if (getListView().getLastVisiblePosition() == (adapter.items.size() - 1))

1 votes

Cela ne permettra pas de détecter si le dernier élément est entièrement visible.

4voto

lazy lord Points 13

Cela peut être

            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                // TODO Auto-generated method stub

                if (scrollState == 2)
                    flag = true;
                Log.i("Scroll State", "" + scrollState);
            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem,
                    int visibleItemCount, int totalItemCount) {
                // TODO Auto-generated method stub
                if ((visibleItemCount == (totalItemCount - firstVisibleItem))
                        && flag) {
                    flag = false;

                    Log.i("Scroll", "Ended");
                }
            }

3voto

zeeshan Points 512

C'était assez pénible de s'occuper du défilement, de détecter quand il est terminé et qu'il est bien en bas de la liste (pas en bas de l'écran visible), et de ne déclencher mon service qu'une seule fois, pour aller chercher des données sur le web. Cependant, cela fonctionne bien maintenant. Le code est le suivant, pour le bénéfice de toute personne confrontée à la même situation.

NOTE : J'ai dû déplacer mon code relatif à l'adaptateur dans onViewCreated au lieu de onCreate et détecter le défilement principalement comme ceci :

public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {}

public void onScrollStateChanged(AbsListView view, int scrollState) {
    if (getListView().getLastVisiblePosition() == (adapter.getCount() - 1))
        if (RideListSimpleCursorAdapter.REACHED_THE_END) {
            Log.v(TAG, "Loading more data");
            RideListSimpleCursorAdapter.REACHED_THE_END = false;
            Intent intent = new Intent(getActivity().getApplicationContext(), FindRideService.class);
            getActivity().getApplicationContext().startService(intent);
        }
}

Ici, RideListSimpleCursorAdapter.REACHED_THE_END est une variable supplémentaire dans mon SimpleCustomAdapter qui est définie comme ceci :

if (position == getCount() - 1) {
      REACHED_THE_END = true;
    } else {
      REACHED_THE_END = false;
    }

Ce n'est que lorsque ces deux conditions sont réunies que cela signifie que je suis effectivement en bas de la liste et que mon service ne sera exécuté qu'une seule fois. Si je n'attrape pas le REACHED_THE_END, même le défilement vers l'arrière déclenche à nouveau le service, tant que le dernier élément est en vue.

0 votes

Je me suis débarrassé de l'autre parce qu'il me causait des problèmes, mais dans l'ensemble, c'est une bonne réponse.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X