web-dev-qa-db-fra.com

Pourquoi les éléments ListView ne parviennent-ils pas à envelopper leur contenu?

J'ai un ListView plutôt complexe, avec des hauteurs d'élément de liste variables. Sous certaines conditions, je dois afficher une vue supplémentaire dans un élément de la liste, qui est masqué par défaut (View.GONE). En l'activant (View.VISIBLE), l'élément de la liste augmente en hauteur (ou du moins, il est supposé le faire).

Le problème: Même si je déclare la disposition racine de l'élément wrap_content, et chaque composant de l'élément à fill_parent, la vue masquée/affichée censée changer la hauteur de l'élément est simplement coupée en bas au lieu de la parent (la disposition de l’article) croît en hauteur pour l’afficher pleinement.

Y at-il des pièges liés à ListViews et à la disposition et à la hauteur des éléments que j'ai peut-être manqués?

Quelques autres observations:

À des fins de test, j'ai maintenant réduit la disposition des éléments de la liste pour qu'elle ne contienne que la racine LinearLayout et un ImageView. Lorsque je règle la hauteur de LinearLayout sur, par exemple, 200dip et ImageView pour fill_parent, je m'attendais à ce que ImageView se développe jusqu'à atteindre la limite de 200dip définie par son parent.

Cependant, au lieu de cela, l’image sera toujours aussi haute que sa ressource bitmap (comme si je l’avais définie sur wrap_content) et l’élément de liste entier sera de la même hauteur (c’est-à-dire comme si je l’avais définie également sur wrap_content).

Si toutefois je règle la hauteur de l'image sur, par exemple, 200dip, l’élément de la liste augmentera en hauteur, de même que la présentation de l’élément.

En d'autres termes, layout_height de la présentation de l'élément de liste est complètement ignoré, de même que toute valeur de hauteur sur ImageView autre qu'une valeur de pixel codée en dur.

55
Matthias

J'ai réussi à résoudre ce problème, mais je ne comprends pas pourquoi .

Comme je l'ai mentionné, j'avais défini le layout_height de la présentation de l'élément de liste sur wrap_content (puisque fill_parent n'a pas de sens ici, étant donné qu'un ListView est indéfiniment grand).

Cependant, j'avais défini le layout_height de toutes les vues inside this layout à fill_parent. Le problème a disparu lorsque vous leur avez attribué la valeur wrap_content.

Cela soulève deux autres questions:

1) Quelle est la sémantique d'une vue demandant à fill_parent, lorsque le parent wraps_content? Quelle demande de taille a la priorité?

2) Comment pourrais-je faire en sorte qu'une vue remplisse un élément de la liste si fill_parent ne fonctionne apparemment pas?

Merci pour votre contribution les gars.

55
Matthias

Essayez ceci: http://www.Java2s.com/Code/Android/UI/setListViewHeightBasedOnChildren.htm

public class Utils {

    public static void setListViewHeightBasedOnChildren(ListView listView) {
        ListAdapter listAdapter = listView.getAdapter(); 
        if (listAdapter == null) {
            // pre-condition
            return;
        }

        int totalHeight = 0;
        for (int i = 0; i < listAdapter.getCount(); i++) {
            View listItem = listAdapter.getView(i, null, listView);
            listItem.measure(0, 0);
            totalHeight += listItem.getMeasuredHeight();
        }

        ViewGroup.LayoutParams params = listView.getLayoutParams();
        params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
        listView.setLayoutParams(params);
        listView.requestLayout();
    }     
}
28
PeBek

Comment gonfles-tu tes rangs?

Si vous ne l'utilisez pas maintenant, essayez d'utiliser LayoutInflater#inflate(layoutId, parent, false) (où parent est la AdapterView fournie à getView() ou newView()):

v = getLayoutInflater().inflate(R.layout.list_item, parent, false);
21
CommonsWare

Les problèmes de mise en page peuvent être causés par ScrollView comme encapsuleur

Je suis tombé sur une note dans http://developer.Android.com/reference/Android/widget/ExpandableListView.html

"... Remarque: vous ne pouvez pas utiliser la valeur wrap_content pour l'attribut Android: layout_height d'un ExpandableListView en XML si la taille du parent n'est pas également spécifiée (par exemple, si le parent était ScrollView, vous ne pourriez pas spécifier wrap_content Vous pouvez toutefois utiliser wrap_content si le parent ExpandableListView a une taille spécifique, telle que 100 pixels. "

J'ai retiré l'emballage de ScrollView et la disposition linéaire a commencé à fonctionner correctement. Maintenant, il n’ya plus qu’à comprendre comment encapsuler le contenu dans ScrollView. Dieu aide moi

Mais de toute façon, c'est un comportement vraiment étrange. Je pense que fill_parent n’est pas vraiment correct. Lorsque j'utilise l'outil heirarchyviewer, je vois toujours les valeurs WRAP_CONTENT et MATCH_PARENT pour layout_width et leayout_height. Donc, probablement fill_parent signifie réellement match_parent, ce qui me met dans une dissonance cognitive.

14
kirhgoff

J'utilise "AbsListView.LayoutParams" pour configurer manuellement la largeur et la hauteur dans "Adapter.getView ()".

1
roys

Si vous utilisez une variable View dans comme élément de la liste en cours de redimensionnement, vous pouvez utiliser la réponse de PeBek et le faire lorsque vous construisez la variable View.

addOnLayoutChangeListener(
            new OnLayoutChangeListener() {
                @Override
                public void onLayoutChange(View _, int __, int ___, int ____, int bottom, int _____, int ______,
                                           int _______, int old_bottom) {
                    final ListView list_view = (ListView) getParent();
                    final ViewGroup.LayoutParams params = list_view.getLayoutParams();
                    params.height += bottom - old_bottom;
                    list_view.setLayoutParams(params);
                    list_view.requestLayout();
                }
            });

Lorsque la variable View sera redimensionnée, cette méthode de rappel sera exécutée et elle mettra à jour la hauteur ListView pour inclure le changement de hauteur (delta bottom). Les autres valeurs, si elles vous sont utiles, sont view (référence à la vue), left, top, right, bottom, old_left, old_top, old_right, old_bottom. Cela fonctionne pour développer et réduire la vue.

API 11 est requis pour OnLayoutChangeListener. Je ne sais pas s'il existe une manière rétro-compatible de le faire.

1
Dandre Allison

ça marche pour moi 

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"

    Android:padding="@dimen/activity_vertical_margin">

    <TextView
        Android:id="@+id/tv_status"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:gravity="center"
        Android:textSize="17sp"
        Android:text="@string/text_list_devices" />

    <ListView
        Android:id="@+id/lv_paired"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:layout_marginTop="@dimen/activity_vertical_margin"
        Android:cacheColorHint="#00000000"
        Android:layout_above="@+id/signup_t"
        Android:layout_below="@id/tv_status"
        />

    <Button

        Android:id="@+id/signup_t"
        style="?android:textAppearanceSmall"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:layout_marginTop="20dp"
        Android:textColor="@Android:color/white"
        Android:layout_alignParentBottom="true"
        Android:text="Print All Records"
        Android:typeface="sans"
        Android:layout_marginLeft="45dp"
        Android:layout_marginRight="45dp"
        Android:textSize="24sp"
        Android:background="@drawable/selector_for_button"
        Android:textStyle="bold" />
</RelativeLayout>
0
Nouman Ch

J'ai eu le même problème: je voudrais avoir une liste dans mon activité qui remplisse tout l'écran, que l'appareil soit vertical ou horizontal .. Je résous le problème en utilisant une disposition linéaire avec une hauteur fill_parent et en définissant la hauteur de l'élément dans la liste sur 0dp, tandis que layout_weight est défini sur 1.

Android:layout_weight="1"
Android:layout_height="0dp"
0
Fra