36 votes

Calculer la taille d'une vue en liste ou comment lui demander de s'étendre complètement

J'essaie actuellement d'utiliser un ListView à l'intérieur d'un ScrollView. Je sais, d'après ce que j'ai lu, que cela est mal vu, mais j'essaie de faire en sorte que le ListView s'étende complètement en affichant toutes ses lignes, de sorte qu'il n'y ait pas besoin de le faire défiler. J'ai cependant du mal à trouver le moyen d'indiquer à la ListView de s'étendre complètement pour afficher toutes ses lignes, car elle a besoin d'une hauteur définie. Comment puis-je calculer la hauteur d'une ListView entièrement développée avant qu'elle ne soit dessinée ?

Ce problème découle principalement du fait que vous ne pouvez pas placer une vue défilable à l'intérieur d'une autre vue défilable. Je suis d'accord avec le fait que le ListView ne pourra pas défiler tant que je peux le faire s'étendre pour montrer toutes ses lignes. Cependant, je ne peux pas faire cela sans pouvoir lui donner une hauteur définie, que je devrais calculer, semble-t-il.

Ma mise en page complète est trop grande pour l'écran "physique" et doit défiler afin d'afficher le reste de la liste et les boutons en bas. J'essaie de faire comprendre que l'écran "virtuel" est trop grand pour tenir sur un seul écran, même sans le ListView.

0 votes

Que signifie "se développer complètement" ?

0 votes

Par "développer complètement", j'entends montrer toutes ses lignes. La question a été modifiée de manière appropriée pour expliquer cela.

0 votes

Il pourrait être utile de poster une capture d'écran ou un croquis de ce que vous essayez d'accomplir. J'ai du mal à comprendre pourquoi le comportement par défaut qui consiste à "développer autant que possible, puis faire défiler s'il y a trop d'éléments à faire tenir" n'est pas suffisant.

57voto

netzpurist Points 711

Eh bien, merci à Rudy, ses suggestions ont été très utiles. Voici comment cela peut être mis en œuvre.

1) Créez une nouvelle classe qui étend ListView :

package com.example.android.views;

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.widget.ListView;

public class ExpandedListView extends ListView {

    private android.view.ViewGroup.LayoutParams params;
    private int old_count = 0;

    public ExpandedListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (getCount() != old_count) {
            old_count = getCount();
            params = getLayoutParams();
            params.height = getCount() * (old_count > 0 ? getChildAt(0).getHeight() : 0);
            setLayoutParams(params);
        }

        super.onDraw(canvas);
    }

}

2) ... et enfin ajouter la nouvelle vue à votre fichier de mise en page xml :

<com.example.android.views.ExpandedListView
    android:id="@+id/list"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:scrollbars="none"
    android:padding="0px"
    />

14 votes

Je n'ai pas essayé, mais d'après ce que je vois, cela ne fonctionne que si tous les éléments ont la même hauteur que getChildAt(0) (ou si, par chance, la taille moyenne exacte des vues est la même que celle de l'image). getChildAt(0).getHeight() )

0 votes

Quelqu'un sait-il comment utiliser ce qui précède dans Xamarin.Android ?

14voto

Romain Piel Points 4269

La façon correcte de calculer la hauteur est précise :

int height = 0;
for (int i = 0; i < listView.getChildCount(); i++) {
    height += listView.getChildAt(i).getMeasuredHeight();
    height += listView.getDividerHeight();
}

11voto

alcsan Points 866

Attention ! La manière correcte de calculer la hauteur n'est pas

params.height = getCount() * (old_count > 0 ? getChildAt(0).getHeight() : 0);

Il faut ajouter la hauteur de chaque séparateur (moins un).

if(oldCount > 0 && getCount() > 0)
    params.height = getCount()
                  * (getChildAt(0).getHeight() + getDividerHeight())
                  - getDividerHeight();
else
    params.height = 0;

1 votes

Notez que cette solution suppose toujours que tous les éléments ont la même hauteur et qu'il n'y a ni pied de page ni en-tête.

0 votes

ListView.getChildAt(0) est null

4voto

ffddani Points 105
@Override
public void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
    if (this.isExpanded) {
        final int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, expandSpec);
        final ViewGroup.LayoutParams params = this.getLayoutParams();
        params.height = this.getMeasuredHeight();
    } else {
       super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

3voto

jqpubliq Points 7677

Si vous voulez un ListView qui ne défile pas, ne pouvez-vous pas simplement utiliser un LinearLayout ?

1 votes

J'aimerais conserver l'aspect natif Android d'une liste sans avoir à déployer la mienne.

0 votes

Vous voulez dire les états en surbrillance ? Dans ce cas, vous pouvez utiliser Android.R.drawable.list_selector_background pour obtenir le même type de comportement, je crois.

0 votes

Oui, ainsi que la fonctionnalité d'en-tête et de pied de page par défaut, les séparateurs de gradient de liste et l'utilisation des constructions d'adaptateur. Je pourrais finir par essayer de faire un clone de ListView en copiant tous les styles intégrés d'Android, mais je voudrais éviter cela si possible.

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