English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Pensée
Aujourd'hui, nous allons réaliser un ListView de chargement supplémentaire en glissant vers le haut. Portail GitHub :PulmListView, bienvenue à fork && star.
Nous allons d'abord clarifier la pensée, si nous devons réaliser un ListView de chargement supplémentaire en glissant vers le haut, les fonctionnalités que nous devons réaliser incluent:
1. Un ListView personnalisé, et ce ListView peut juger si il est déjà au bas.
2. Un FooterView personnalisé, utilisé pour afficher l'UI pendant le chargement supplémentaire de ListView.
3. Associate FooterView et ListView, y compris le jugement du moment de chargement, l'affichage et le masquage de FooterView.
4. Fournir une interface de chargement supplémentaire, facilitant le rappel de la fonction de chargement supplémentaire réelle de l'utilisateur.
5. Fournir une méthode de rappel de fin de chargement supplémentaire, utilisée pour ajouter les données les plus récentes de l'utilisateur et mettre à jour les marqueurs de statut et l'affichage UI.
Pour les éléments mentionnés ci-dessus5fonctionnalités, nous analysons individuellement les méthodes correspondantes.
Fonctionnalité1(ListView personnalisé)
Nous pouvons hériter de ListView pour réaliser un PulmListView personnalisé.
public class PulmListView extends ListView { public PulmListView(Context context) { this(context, null); } public PulmListView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public PulmListView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); // Initialisation init(); } }
Il ne suffit pas de réaliser les trois constructeurs de ListView, nous devons également que la ListView puisse juger si elle a glissé jusqu'au dernier élément.
Pour判断是否滑动到最后一个元素, nous pouvons définir un OnScrollListener pour la ListView. Le code est le suivant :
private void init() { super.setOnScrollListener(new OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { // Appeler le OnScrollListener configuré par l'utilisateur if (mUserOnScrollListener != null) { mUserOnScrollListener.onScrollStateChanged(view, scrollState); } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { // Appeler le OnScrollListener configuré par l'utilisateur if (mUserOnScrollListener != null) { mUserOnScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount); } // firstVisibleItem est la position de l'élément premier visible sur l'écran // visibleItemCount est le nombre d'éléments affichables sur l'écran // totalItemCount est le nombre total d'éléments contenus dans la ListView int lastVisibleItem = firstVisibleItem + visibleItemCount; if (!mIsLoading && !mIsPageFinished && lastVisibleItem == totalItemCount) { if (mOnPullUpLoadMoreListener != null) {}} mIsLoading = true; mOnPullUpLoadMoreListener.onPullUpLoadMore(); } } } }); }
D'après les commentaires du code, on peut savoir que par l'intermédiaire de (firstVisibleItem + visibleItemCount) permet de récupérer le nombre d'éléments déjà affichés sur l'écran, si le nombre d'éléments affichés est égal au nombre total d'éléments de la ListView, alors on peut considérer que la ListView a glissé en bas.
Fonctionnalité2(Vue de pied personnalisée)
Ici, nous pouvons réaliser un FooterView assez simple, c'est-à-dire un layout d'UI pour charger plus. Par exemple, nous pouvons afficher un ProgressBar et une ligne de texte, le code spécifique est le suivant :
/** * Layout de vue pour charger plus, personnalisable. */ public class LoadMoreView extends LinearLayout { public LoadMoreView(Context context) { this(context, null); } public LoadMoreView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public LoadMoreView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { LayoutInflater.from(getContext()).inflate(R.layout.lv_load_more, this); } }
Fichier de conception:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@"+id/id_load_more_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center" android:layout_margin="@dimen/loading_view_margin_layout"> <ProgressBar android:id="@"+id/id_loading_progressbar" android:layout_width="@dimen/loading_view_progress_size" android:layout_height="@dimen/loading_view_progress_size" android:indeterminate="true" style="?android:progressBarStyleSmall"/> <TextView android:id="@"+id/id_loading_label" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/page_loading"/> </LinearLayout>
Fonctionnalité3(Liée à ListView et FooterView)
Premièrement, nous devons sauvegarder FooterView dans une variable de ListView et l'instancier dans le constructeur.
private View mLoadMoreView; private void init() { mLoadMoreView = new LoadMoreView(getContext()); }
Deuxièmement, nous devons contrôler l'affichage et le masquage de FooterView. Considérons les moments d'affichage et de masquage de FooterView :
•Le moment visible : La liste de View est au bas et il y a encore plus de données à charger.
•Le moment caché : La liste de View a terminé l'opération de chargement supplémentaire.
Pour déterminer s'il y a encore des données à charger, nous devons définir une variable boolean mIsPageFinished pour indiquer si le chargement des données est terminé.
Pour s'assurer que seules les données sont chargées une fois à la fois, nous devons également définir une variable boolean mIsLoading pour indiquer si nous sommes déjà en train de charger des données.
Nous avons clarifié le moment d'affichage et de masquage du FooterView, ainsi que les variables de contrôle de l'état, ce qui rend le code plus facile à réaliser.
Moment d'affichage :
private void init() { mIsLoading = false; // L'initialisation n'est pas en cours de chargement mIsPageFinished = false; // Par défaut, il y a encore plus de données à charger lors de l'initialisation mLoadMoreView = new LoadMoreView(getContext()); // Créer une instance de FooterView super.setOnScrollListener(new OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { // Appeler le OnScrollListener configuré par l'utilisateur if (mUserOnScrollListener != null) { mUserOnScrollListener.onScrollStateChanged(view, scrollState); } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { // Appeler le OnScrollListener configuré par l'utilisateur if (mUserOnScrollListener != null) { mUserOnScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount); } int lastVisibleItem = firstVisibleItem + visibleItemCount; // Lorsque l'on est à la fin de la ListView et qu'il y a plus de données à charger sans autre programme de chargement en cours, exécuter l'opération de chargement supplémentaire if (!mIsLoading && !mIsPageFinished && lastVisibleItem == totalItemCount) { if (mOnPullUpLoadMoreListener != null) {}} mIsLoading = true; // Définir l'état de chargement supplémentaire en cours comme true showLoadMoreView(); // Afficher le layout de chargement supplémentaire mOnPullUpLoadMoreListener.onPullUpLoadMore(); // Appeler l'interface de callback de chargement supplémentaire définie par l'utilisateur } } } }); } private void showLoadMoreView() { // Ici, l'id de la racine du layout de chargement supplémentaire est défini comme id_load_more_layout, pour faciliter la personnalisation du layout de chargement supplémentaire par l'utilisateur. if (findViewById(R.id.id_load_more_layout) == null) { addFooterView(mLoadMoreView); } }
Moment de masquage :
/** * Méthode de rappel ListView après le chargement supplémentaire * * @param isPageFinished Est-ce que la pagination est terminée * @param newItems Données de chargement par pagination * @param isFirstLoad Est-ce que c'est le premier chargement des données (utilisé pour configurer le cadre de rafraîchissement en descendant, pour éviter l'apparition de la page flash) */ public void onFinishLoading(boolean isPageFinished, List<63;> newItems, boolean isFirstLoad) { mIsLoading = false; // Marquer que la page actuelle n'a plus de programme de chargement supplémentaire en cours d'exécution setIsPageFinished(isPageFinished); // Définir le drapeau d'achèvement de pagination et supprimer FooterView } private void setIsPageFinished(boolean isPageFinished) { mIsPageFinished = isPageFinished; removeFooterView(mLoadMoreView); }
Fonctionnalité4(Interface de callback pour l'implémentation de chargement supplémentaire en haut du défilement)
Cela est assez simple, nous définissons une interface pour faciliter le callback de la méthode réelle de chargement supplémentaire de l'utilisateur.
/** * Interface de callback de chargement supplémentaire en haut du défilement */ public interface OnPullUpLoadMoreListener { void onPullUpLoadMore(); } private OnPullUpLoadMoreListener mOnPullUpLoadMoreListener; /** * Définir l'interface de callback de chargement supplémentaire en haut du défilement. * @param l Interface de callback de chargement supplémentaire en haut du défilement */ public void setOnPullUpLoadMoreListener(OnPullUpLoadMoreListener l) { this.mOnPullUpLoadMoreListener = l; }
Fonctionnalité5(Callback de fin de chargement supplémentaire)
Pour maintenir les ensembles de données dans PulmListView, il est nécessaire de définir un adaptateur personnalisé, dans lequel on utilise une liste pour stocker l'ensemble des données et soumettre des méthodes d'ajout et de suppression.
Adapter personnalisé:
/** * Adapter abstrait. */ public abstract class PulmBaseAdapter<T> extends BaseAdapter { protected List<T> items; public PulmBaseAdapter() { this.items = new ArrayList<>(); } public PulmBaseAdapter(List<T> items) { this.items = items; } public void addMoreItems(List<T> newItems, boolean isFirstLoad) { if (isFirstLoad) { this.items.clear(); } this.items.addAll(newItems); notifyDataSetChanged(); } public void removeAllItems() { this.items.clear(); notifyDataSetChanged(); } }
Pourquoi ajouter une variable isFirstLoad dans la méthode addMoreItems ?
C'est parce que le chargement supplémentaire par glissement vers le haut doit généralement être utilisé avec le rafraîchissement en descendant. Pendant le processus de rafraîchissement en descendant, il implique la collection de données ListView clear puis addAll. Sans le paramètre isFirstLoad, pour que l'utilisateur puisse mettre à jour la collection de données ListView en descendant, il doit être divisé en deux étapes:
1.removeAllItems et ensuite notifyDataSetChanged.
2.addMoreItems et ensuite notifyDataSetChanged.
Deux notifications successives de notifyDataSetChanged dans un même temps peuvent entraîner un écran clignotant, donc ici, une méthode isFirstLoad a été soumise. Lorsque c'est le premier chargement des données, tous les données sont d'abord clearés, puis addAll, et enfin notify.
Avec un adapter personnalisé, vous pouvez écrire une fonction de rappel de fin de chargement supplémentaire:
/** * Méthode de rappel ListView après le chargement supplémentaire * * @param isPageFinished Est-ce que la pagination est terminée * @param newItems Données de chargement par pagination * @param isFirstLoad Est-ce que c'est le premier chargement des données (utilisé pour configurer le cadre de rafraîchissement en descendant, pour éviter l'apparition de la page flash) */ public void onFinishLoading(boolean isPageFinished, List<63;> newItems, boolean isFirstLoad) { mIsLoading = false; setIsPageFinished(isPageFinished); // Ajouter les données mis à jour if (newItems != null && newItems.size() > 0) { PulmBaseAdapter adapter = (PulmBaseAdapter) ((HeaderViewListAdapter) getAdapter()).getWrappedAdapter(); adapter.addMoreItems(newItems, isFirstLoad); } }
Il faut noter ici, après avoir ajouté FooterView ou HeaderView, nous ne pouvons pas obtenir notre adapter personnalisé via listview.getAdapter, nous devons suivre les étapes suivantes :
PulmBaseAdapter adapter = (PulmBaseAdapter) ((HeaderViewListAdapter) getAdapter()).getWrappedAdapter();
Référence
1.PagingListView
Voici la totalité du contenu de cet article, j'espère qu'il vous sera utile dans vos études, et j'espère que vous soutiendrez également le tutoriel d'alarme.
Déclaration : le contenu de cet article est issu du réseau, et appartient aux auteurs respectifs. Le contenu est apporté par les utilisateurs d'Internet et téléchargé spontanément. Le site Web ne détient pas de propriété, n'a pas été édité par l'homme, et n'assume aucune responsabilité juridique connexe. Si vous trouvez du contenu présumé enfreindre les droits d'auteur, veuillez envoyer un e-mail à : notice#oldtoolbag.com (veuillez remplacer # par @ lors de l'envoi d'un e-mail pour signaler une violation, et fournir des preuves pertinentes. Une fois vérifié, le site supprimera immédiatement le contenu présumé enfreindre les droits d'auteur.)