J'ai cherché des solutions à ce problème, et la seule réponse que je peux trouver semble être " ne mettez pas un ListView dans un ScrollView ". Je n'ai pas encore vu d'explication réelle pour expliquer pourquoi . La seule raison pour laquelle je peux sembler trouver est que Google ne pense pas que vous devriez vouloir faire cela. Eh bien, je l'ai fait.
La question est donc de savoir comment placer un ListView dans un ScrollView sans qu'il ne s'effondre à sa hauteur minimale?
ListView
.ListView
peut avoir plusieurs styles de ligne, plus des lignes non sélectionnables.Réponses:
Utiliser un
ListView
pour ne pas faire défiler est extrêmement coûteux et va à l'encontre de l'objectif deListView
. Vous ne devriez PAS faire cela. Utilisez simplement un à laLinearLayout
place.la source
How can I put a ListView into a ScrollView without it collapsing?
... Vous pouvez dire que vous ne devriez pas le faire, mais aussi donner une réponse sur la façon de le faire, c'est une bonne réponse. Vous savez qu'un ListView a d'autres fonctionnalités intéressantes en dehors du défilement, des fonctionnalités que LinearLayout n'a pas.Voici ma solution. Je suis assez nouveau sur la plate-forme Android, et je suis sûr que c'est un peu piraté, en particulier dans la partie concernant l'appel direct de .measure et la définition
LayoutParams.height
directe de la propriété, mais cela fonctionne.Tout ce que vous avez à faire est d'appeler
Utility.setListViewHeightBasedOnChildren(yourListView)
et il sera redimensionné pour s'adapter exactement à la hauteur de ses articles.la source
LinearLayout
n'a pas toutes les subtilités inhérentes à aListView
- il n'a pas de séparateurs, de vues en-tête / pied de page, un sélecteur de liste qui correspond aux couleurs du thème de l'interface utilisateur du téléphone, etc. Honnêtement, il n'y a aucune raison pour laquelle vous ne pouvez pas faire défiler le conteneur interne jusqu'à ce qu'il atteigne la fin, puis faites-le cesser d'intercepter les événements tactiles afin que le conteneur externe défile. Chaque navigateur de bureau le fait lorsque vous utilisez votre molette de défilement. Android lui-même peut gérer le défilement imbriqué si vous naviguez via le trackball, alors pourquoi pas via le toucher?listItem.measure(0,0)
va lancer un NPE si listItem est une instance de ViewGroup. J'ai ajouté ce qui suit avantlistItem.measure
:if (listItem instanceof ViewGroup) listItem.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
int totalHeight = listView.getPaddingTop() + listView.getPaddingBottom();
ListView
peut contenir des éléments de hauteur variable. L'appel àgetMeasuredHeight()
renvoie uniquement la hauteur minimale ciblée par opposition à la hauteur réelle. J'ai essayé d'utiliser à lagetHeight()
place, mais cela renvoie 0. Quelqu'un at-il une idée de la façon d'aborder cela?Cela fonctionnera certainement ............
Vous devez simplement remplacer votre
<ScrollView ></ScrollView>
fichier XML de mise en page par ceciCustom ScrollView
comme<com.tmd.utils.VerticalScrollview > </com.tmd.utils.VerticalScrollview >
la source
Au lieu de mettre à l'
ListView
intérieur d'unScrollView
, on peut l'utiliserListView
comme unScrollView
. Les objets qui doiventListView
être placés peuvent être placés à l'intérieur duListView
. D'autres dispositions en haut et en bas deListView
peuvent être ajoutées en ajoutant des dispositions à l'en-tête et au pied de page deListView
. Ainsi, l'ensembleListView
vous donnera une expérience de défilement.la source
Il existe de nombreuses situations où il est très logique d'avoir ListView dans un ScrollView.
Voici le code basé sur la suggestion de DougW ... fonctionne dans un fragment, prend moins de mémoire.
appelez setListViewHeightBasedOnChildren (listview) sur chaque listview incorporée.
la source
ListView est en fait déjà capable de se mesurer pour être suffisamment grand pour afficher tous les éléments, mais il ne le fait pas lorsque vous spécifiez simplement wrap_content (MeasureSpec.UNSPECIFIED). Il le fera lorsqu'il recevra une hauteur avec MeasureSpec.AT_MOST. Avec ces connaissances, vous pouvez créer une sous-classe très simple pour résoudre ce problème qui fonctionne bien mieux que toutes les solutions publiées ci-dessus. Vous devez toujours utiliser wrap_content avec cette sous-classe.
La manipulation de heightMeasureSpec pour être AT_MOST avec une très grande taille (Integer.MAX_VALUE >> 4) oblige le ListView à mesurer tous ses enfants jusqu'à la hauteur donnée (très grande) et à définir sa hauteur en conséquence.
Cela fonctionne mieux que les autres solutions pour plusieurs raisons:
À la baisse, vous pourriez faire valoir que cela dépend de comportements non documentés dans le SDK qui pourraient changer. D'un autre côté, vous pourriez affirmer que c'est ainsi que wrap_content devrait vraiment fonctionner avec ListView et que le comportement actuel de wrap_content est simplement rompu.
Si vous craignez que le comportement puisse changer à l'avenir, vous devez simplement copier la fonction onMeasure et les fonctions connexes à partir de ListView.java et dans votre propre sous-classe, puis faire également le chemin AT_MOST via onMeasure pour UNSPECIFIED.
Soit dit en passant, je pense que c'est une approche parfaitement valable lorsque vous travaillez avec un petit nombre d'éléments de liste. Il peut être inefficace par rapport à LinearLayout, mais lorsque le nombre d'éléments est petit, l'utilisation de LinearLayout est une optimisation inutile et donc une complexité inutile.
la source
Il y a un paramètre intégré pour cela. Sur le ScrollView:
En Java,
Romain Guy l'explique en détail ici: http://www.curious-creature.org/2010/08/15/scrollviews-handy-trick/
la source
Vous créez une ListView personnalisée qui n'est pas défilable
Dans votre fichier de ressources de mise en page
Dans un fichier Java
Créez un objet de votre customListview au lieu de ListView comme: NonScrollListView non_scroll_list = (NonScrollListView) findViewById (R.id.lv_nonscroll_list);
la source
Nous ne pourrions pas utiliser deux défilements simultanés. Nous aurons la longueur totale de ListView et développerons listview avec la hauteur totale. Ensuite, nous pouvons ajouter ListView dans ScrollView directement ou en utilisant LinearLayout car ScrollView a directement un enfant. copiez la méthode setListViewHeightBasedOnChildren (lv) dans votre code et développez listview puis vous pouvez utiliser listview dans scrollview. \ layout xml file
Méthode onCreate dans la classe Activity:
la source
Ceci est une combinaison des réponses de DougW, Good Guy Greg et Paul. J'ai trouvé que tout était nécessaire lorsque j'essayais de l'utiliser avec un adaptateur listview personnalisé et des éléments de liste non standard, sinon listview plantait l'application (également plantée avec la réponse de Nex):
la source
Vous ne devez pas placer un ListView dans un ScrollView car un ListView est déjà un ScrollView. Ce serait donc comme mettre un ScrollView dans un ScrollView.
Qu'est-ce que vous essayez d'accomplir?
la source
J'ai converti @ DougW's
Utility
en C # (utilisé dans Xamarin). Ce qui suit fonctionne très bien pour les éléments à hauteur fixe dans la liste, et sera généralement très bien, ou du moins un bon début, si seulement certains des éléments sont un peu plus gros que l'élément standard.Merci @DougW, cela m'a permis de sortir d'une situation difficile lorsque je devais travailler avec OtherPeople'sCode. :-)
la source
setListViewHeightBasedOnChildren()
méthode? Parce que ça ne marche pas tout le temps pour moi.C'est la seule chose qui a fonctionné pour moi:
sur Lollipop, vous pouvez utiliser
Cela active ou désactive le défilement imbriqué pour cette vue si vous avez besoin d'une compatibilité descendante avec une ancienne version du système d'exploitation, vous devrez utiliser RecyclerView.
la source
Avant, ce n'était pas possible. Mais avec la sortie de nouvelles bibliothèques Appcompat et de bibliothèques de conception, cela peut être réalisé.
Il vous suffit d'utiliser NestedScrollView https://developer.android.com/reference/android/support/v4/widget/NestedScrollView.html
Je ne sais pas si cela fonctionnera avec Listview ou non, mais fonctionne avec RecyclerView.
Extrait de code:
la source
hey j'avais un problème similaire. Je voulais afficher une vue de liste qui ne défilait pas et j'ai trouvé que la manipulation des paramètres fonctionnait mais était inefficace et se comporterait différemment sur différents appareils .. en conséquence, c'est un morceau de mon code de programmation qui le fait en fait très efficacement .
Remarque: si vous utilisez cela,
notifyDataSetChanged();
ne fonctionnera pas comme prévu car les vues ne seront pas redessinées. Faites-le si vous avez besoin d'une solutionla source
Il existe deux problèmes lors de l'utilisation d'un ListView dans un ScrollView.
1- ListView doit s'étendre complètement à la hauteur de ses enfants. ce ListView résoudre ce problème:
La hauteur du séparateur doit être égale à 0, utilisez plutôt un remplissage dans les lignes.
2- Le ListView consomme des événements tactiles afin que ScrollView ne puisse pas défiler comme d'habitude. Ce ScrollView résout ce problème:
C'est le meilleur moyen que j'ai trouvé pour faire l'affaire!
la source
Une solution que j'utilise est d'ajouter tout le contenu du ScrollView (ce qui devrait être au-dessus et en dessous du listView) en tant que headerView et footerView dans le ListView.
Donc, cela fonctionne comme, la convertview est également redéfinie comme elle devrait être.
la source
grâce au code de Vinay voici mon code pour quand vous ne pouvez pas avoir une vue de liste dans une vue de défilement mais vous avez besoin de quelque chose comme ça
le relativeLayout reste à l'intérieur d'un ScrollView donc tout devient scrollable :)
la source
Voici une petite modification sur la réponse de @djunod dont j'ai besoin pour le faire fonctionner parfaitement:
la source
essayez ceci, cela fonctionne pour moi, j'ai oublié où je l'ai trouvé, quelque part dans le débordement de pile, je ne suis pas ici pour expliquer pourquoi cela ne fonctionne pas, mais c'est la réponse :).
EDIT!, J'ai finalement découvert où j'avais obtenu le code. ici ! : ListView dans ScrollView ne défile pas sur Android
la source
Bien que les méthodes setListViewHeightBasedOnChildren () suggérées fonctionnent dans la plupart des cas, dans certains cas, spécialement avec beaucoup d'éléments, j'ai remarqué que les derniers éléments ne sont pas affichés. J'ai donc décidé d'imiter une version simple du comportement ListView afin de réutiliser n'importe quel code adaptateur, voici l'alternative ListView:
la source
Toutes ces réponses sont fausses !!! Si vous essayez de mettre une vue de liste dans une vue de défilement, vous devez repenser votre conception. Vous essayez de mettre un ScrollView dans un ScrollView. Interférer avec la liste nuira aux performances de la liste. Il a été conçu pour être comme ça par Android.
Si vous voulez vraiment que la liste soit dans le même défilement que les autres éléments, tout ce que vous avez à faire est d'ajouter les autres éléments en haut de la liste à l'aide d'une simple instruction switch dans votre adaptateur:
L'adaptateur de liste peut tout gérer car il ne rend que ce qui est visible.
la source
Tout ce problème disparaîtrait si LinearLayout avait une méthode setAdapter, car alors, lorsque vous avez dit à quelqu'un de l'utiliser à la place, l'alternative serait triviale.
Si vous voulez réellement un ListView défilant dans une autre vue défilante, cela ne vous aidera pas, mais sinon cela vous donnera au moins une idée.
Vous devez créer un adaptateur personnalisé pour combiner tout le contenu que vous souhaitez faire défiler et définir l'adaptateur de ListView sur celui-ci.
Je n'ai pas d'exemple de code à portée de main, mais si vous voulez quelque chose comme.
Ensuite, vous devez créer un adaptateur qui représente tout ce contenu. Les ListView / Adapters sont suffisamment intelligents pour gérer également différents types, mais vous devez écrire l'adaptateur vous-même.
L'API Android UI n'est tout simplement pas aussi mature que tout le reste, donc elle n'a pas les mêmes subtilités que les autres plates-formes. De plus, lorsque vous faites quelque chose sur Android, vous devez être dans un état d'esprit Android (Unix) où vous vous attendez à ce que pour faire quoi que ce soit, vous devrez probablement assembler des fonctionnalités de petites pièces et écrire un tas de votre propre code pour l'obtenir. travail.
la source
Lorsque nous nous plaçons à l'
ListView
intérieur,ScrollView
deux problèmes surgissent. L'unScrollView
mesure ses enfants en mode NON SPÉCIFIÉ,ListView
définit donc sa propre hauteur pour accueillir un seul élément (je ne sais pas pourquoi), un autreScrollView
intercepte l'événement tactile etListView
ne défile pas.Mais nous pouvons placer à l'
ListView
intérieurScrollView
avec une solution de contournement. Ce message , par moi, explique la solution de contournement. Grâce à cette solution de contournement, nous pouvons également conserverListView
la fonction de recyclage de.la source
Au lieu de placer la vue de liste dans Scrollview, placez le reste du contenu entre la vue de liste et l'ouverture de Scrollview en tant que vue distincte et définissez cette vue comme en-tête de la vue de liste. Vous finirez donc par ne voir que la liste en prenant en charge Scroll.
la source
Cette bibliothèque est la solution la plus simple et la plus rapide au problème.
la source
Voici ma version du code qui calcule la hauteur totale de la vue liste. Celui-ci fonctionne pour moi:
la source