236 votes

Android Liste Interminable

Comment puis-je créer une liste où lorsque vous atteignez la fin de la liste, je suis informé si je peux charger plus d'articles?

270voto

Josef Pfleger Points 37003

Une solution est de mettre en œuvre un OnScrollListener et de faire des changements (comme l'ajout d'éléments, etc.) à l' ListAdapter à une pratique de l'état dans ses onScroll méthode.

La suite de ListActivity montre une liste d'entiers, à commencer par 40, ajout d'éléments lorsque l'utilisateur fait défiler à la fin de la liste.

public class Test extends ListActivity implements OnScrollListener {

    Aleph0 adapter = new Aleph0();

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setListAdapter(adapter); 
        getListView().setOnScrollListener(this);
    }

    public void onScroll(AbsListView view,
        int firstVisible, int visibleCount, int totalCount) {

        boolean loadMore = /* maybe add a padding */
            firstVisible + visibleCount >= totalCount;

        if(loadMore) {
            adapter.count += visibleCount; // or any other amount
            adapter.notifyDataSetChanged();
        }
    }

    public void onScrollStateChanged(AbsListView v, int s) { }    

    class Aleph0 extends BaseAdapter {
        int count = 40; /* starting amount */

        public int getCount() { return count; }
        public Object getItem(int pos) { return pos; }
        public long getItemId(int pos) { return pos; }

        public View getView(int pos, View v, ViewGroup p) {
                TextView view = new TextView(Test.this);
                view.setText("entry " + pos);
                return view;
        }
    }
}

Vous devez évidemment utiliser des threads séparés pendant de longues actions en cours d'exécution (comme le chargement web de données) et pourrait vouloir indiquer les progrès accomplis dans le dernier élément de la liste (comme le marché ou gmail apps).

93voto

saschoar Points 2433

Juste voulu contribuer à une solution que j'ai utilisé pour mon application.

Il est également basé sur l' OnScrollListener interface, mais je l'ai trouvé un peu mieux les performances de défilement sur le bas de gamme des appareils, car aucun de visible/nombre total calculs sont effectués pendant le défilement des opérations.

  1. Laissez votre ListFragment ou ListActivity œuvre OnScrollListener
  2. Ajoutez les méthodes suivantes à la classe:

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) {
        //leave this empty
    }
    
    @Override
    public void onScrollStateChanged(AbsListView listView, int scrollState) {
        if (scrollState == SCROLL_STATE_IDLE) {
            if (listView.getLastVisiblePosition() >= listView.getCount() - 1 - threshold) {
                currentPage++;
                //load more list items:
                loadElements(currentPage);
            }
        }
    }
    

    currentPage est la page de votre source de données qui devrait être ajouté à votre liste, et threshold est le nombre d'éléments de la liste (comptées à partir de la fin) qui devrait, si elle est visible, déclencher le processus de chargement. Si vous définissez threshold de 0, par exemple, l'utilisateur doit faire défiler jusqu'à la fin de la liste dans l'ordre de charger plus d'articles.

  3. (facultatif) Comme vous pouvez le voir, la "charge-plus de vérifier" n'est appelée lorsque l'utilisateur cesse de défiler. Pour améliorer la facilité d'utilisation, vous pouvez gonfler et ajouter un indicateur de chargement à la fin de la liste via listView.addFooterView(yourFooterView). Un exemple pour un tel pied de page vue:

    <?xml version="1.0" encoding="utf-8"?>
    
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/footer_layout"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:padding="10dp" >
    
        <ProgressBar
            android:id="@+id/progressBar1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_gravity="center_vertical" />
    
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_toRightOf="@+id/progressBar1"
            android:padding="5dp"
            android:text="@string/loading_text" />
    
    </RelativeLayout>
    
  4. (facultatif) Enfin, supprimez l'indicateur de chargement en appelant listView.removeFooterView(yourFooterView) si il n'y a pas plus d'articles ou de pages.

20voto

DariuszB Points 2427

Vous pouvez détecter la fin de la liste avec l'aide de onScrollListener, code de travail est présenté ci-dessous:

@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
    if (view.getAdapter() != null && ((firstVisibleItem + visibleItemCount) >= totalItemCount) && totalItemCount != mPrevTotalItemCount) {
        Log.v(TAG, "onListEnd, extending list");
        mPrevTotalItemCount = totalItemCount;
        mAdapter.addMoreData();
    }
}

Une autre façon de le faire (à l'intérieur de l'adaptateur) est comme suit:

    public View getView(int pos, View v, ViewGroup p) {
            if(pos==getCount()-1){
                addMoreData(); //should be asynctask or thread
            }
            return view;
    }

Sachez que cette méthode sera appelée de nombreuses fois, vous devez ajouter une autre condition pour bloquer les appels multiples de addMoreData().

Lorsque vous ajoutez des éléments à la liste, veuillez appeler notifyDataSetChanged() à l'intérieur de la vôtre adaptateur pour mettre à jour la Vue (il doit être exécuté sur le thread d'INTERFACE utilisateur - runOnUiThread)

2voto

Fernando Camargo Points 1046

Voici une solution qui permet également de montrer un chargement de vue à la fin de la liste alors que c'est le chargement.

Vous pouvez voir les classes ici:

https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/helper/ListViewWithLoadingIndicatorHelper.java - De l'aide pour permettre d'utiliser les fonctionnalités sans s'étendant à partir de SimpleListViewWithLoadingIndicator.

https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/listener/EndlessScrollListener.java - Auditeur qui commence le chargement de données lorsque l'utilisateur est sur le point d'atteindre le bas de la liste.

https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/view/SimpleListViewWithLoadingIndicator.java - Le EndlessListView. Vous pouvez utiliser cette classe directement ou étendre.

0voto

pabloverd Points 219

J'ai travaillé dans une autre solution, très semblable à cela, mais, je suis en utilisant un footerView de donner la possibilité à l'utilisateur de télécharger plus d'éléments en cliquant sur le footerView, je suis à l'aide d'un "menu" qui est affiché au dessus de la ListView et en bas de la vue parent, cette "menu" cache le bas de la liste, de sorte que, lorsque la liste est de défilement, le menu disparaît et quand de défilement de l'état est inactif, le menu s'affiche de nouveau, mais lorsque l'utilisateur fait défiler à la fin de la liste, J' "demander" pour savoir si le footerView est montré dans ce cas, le menu ne s'affiche pas et l'utilisateur peut voir les footerView pour charger plus de contenu. Voici le code:

Ce qui concerne.

        listView.setOnScrollListener(new OnScrollListener() {

        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
            // TODO Auto-generated method stub
            if(scrollState == SCROLL_STATE_IDLE)
            {
                if(footerView.isShown())
                    bottomView.setVisibility(LinearLayout.INVISIBLE);
                else
                    bottomView.setVisibility(LinearLayout.VISIBLE);
            }else{
                bottomView.setVisibility(LinearLayout.INVISIBLE);
            }
        }

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

        }
    });

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