web-dev-qa-db-fra.com

Android: pourquoi n'y a-t-il pas maxHeight pour une vue?

Les vues ont un minHeight mais il leur manque un maxHeight:

Ce que je cherche à faire, c’est que certains éléments (vues) remplissent un ScrollView. Quand il y a des articles 1..3, je veux les afficher directement. Ce qui signifie que ScrollView a la hauteur de 1, 2 ou 3 éléments.

Quand il y a 4 éléments ou plus, je veux que le ScrollView cesse de se développer (donc un maxHeight) et commence à fournir le défilement.

Cependant, il n’existe malheureusement aucun moyen de définir un maxHeight. Donc, je dois probablement définir ma hauteur ScrollView par programme à WRAP_CONTENT Lorsqu'il y a des éléments 1..3 et définir la hauteur à 3*sizeOf(View) lorsqu'il y a 4 éléments ou plus .

Quelqu'un peut-il expliquer pourquoi il n'y a pas de maxHeight fourni, alors qu'il y a déjà un minHeight?

(BTW: certaines vues, comme ImageView ont un maxHeight implémenté.)

164
znq

Aucune de ces solutions ne fonctionnait pour ce dont j'avais besoin, à savoir un ScrollView défini sur wrap_content, mais avec un maxHeight afin qu'il cesse de se développer après un certain point et commence à défiler. Je viens simplement de surcharger la méthode onMeasure dans ScrollView.

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    heightMeasureSpec = MeasureSpec.makeMeasureSpec(300, MeasureSpec.AT_MOST);
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

Cela peut ne pas fonctionner dans toutes les situations, mais cela me donne certainement les résultats nécessaires pour ma mise en page. Et cela répond aussi au commentaire de madhu.

Si une mise en page est présente sous le scrollview, cette astuce ne fonctionnera pas - madhu 5 mars à 4:36

78
whizzle

Pour créer un ScrollView ou ListView avec un maxHeight, il vous suffit de créer un objet LinearLayout transparent avec une hauteur correspondant à ce que vous souhaitez que maxHeight soit. Vous définissez ensuite la hauteur de ScrollView sur wrap_content. Cela crée un ScrollView qui semble grossir jusqu'à ce que sa hauteur soit égale à celle de LinearLayout parent.

68
JustinMorris

Cela a fonctionné pour moi pour le rendre personnalisable en xml:

MaxHeightScrollView.Java:

public class MaxHeightScrollView extends ScrollView {

private int maxHeight;
private final int defaultHeight = 200;

public MaxHeightScrollView(Context context) {
    super(context);
}

public MaxHeightScrollView(Context context, AttributeSet attrs) {
    super(context, attrs);
    if (!isInEditMode()) {
        init(context, attrs);
    }
}

public MaxHeightScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    if (!isInEditMode()) {
        init(context, attrs);
    }
}

@TargetApi(Build.VERSION_CODES.Lollipop)
public MaxHeightScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
    if (!isInEditMode()) {
        init(context, attrs);
    }
}

private void init(Context context, AttributeSet attrs) {
    if (attrs != null) {
        TypedArray styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.MaxHeightScrollView);
        //200 is a defualt value
        maxHeight = styledAttrs.getDimensionPixelSize(R.styleable.MaxHeightScrollView_maxHeight, defaultHeight);

        styledAttrs.recycle();
    }
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST);
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}

attr.xml

<declare-styleable name="MaxHeightScrollView">
        <attr name="maxHeight" format="dimension" />
    </declare-styleable>

exemple de mise en page

<blah.blah.MaxHeightScrollView Android:layout_weight="1"
                app:maxHeight="90dp"
                Android:layout_width="fill_parent"
                Android:layout_height="wrap_content">
                <EditText Android:id="@+id/commentField"
                    Android:hint="Say Something"
                    Android:background="#FFFFFF"
                    Android:paddingLeft="8dp"
                    Android:paddingRight="8dp"
                    Android:gravity="center_vertical"
                    Android:maxLines="500"
                    Android:minHeight="36dp"
                    Android:layout_width="fill_parent"
                    Android:layout_height="wrap_content" />
            </blah.blah.MaxHeightScrollView>
35
SlickDev

(Je sais que cela ne répond pas directement à la question, mais pourrait être utile aux autres personnes à la recherche de la fonctionnalité maxHeight)

ConstraintLayout offre une hauteur maximale à ses enfants via

app:layout_constraintHeight_max="300dp"
app:layout_constrainedHeight="true" 

ou

app:layout_constraintWidth_max="300dp"
app:layout_constrainedWidth="true" 

Exemple d'utilisation ici .

12
user1506104

J'aurais commenté la réponse de Whizzle si je le pouvais, mais je pensais qu'il était utile de noter que pour que je puisse résoudre ce problème dans le contexte du mode multi-fenêtre dans Android N, je devais modifiez légèrement le code en ceci:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    if(MeasureSpec.getSize(heightMeasureSpec) > maxHeight) {
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST);
    }
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

Cela permet de redimensionner la mise en page pour qu'elle soit inférieure à la hauteur maximale, mais l'empêche également d'être plus grande que la hauteur maximale. J’ai utilisé c’est une classe de présentation qui remplace RelativeLayout, ce qui m’a permis de créer une boîte de dialogue personnalisée avec un ScrollView comme enfant de MaxHeightRelativeLayout qui ne développe pas toute la hauteur de l'écran et réduit également pour tenir dans la plus petite taille de la veuve en multi-fenêtre pour Android N.

7
J. P. Krause

Il n'y a aucun moyen de définir maxHeight. Mais vous pouvez définir la hauteur.

Pour ce faire, vous devrez découvrir la hauteur de chaque élément de scrollView. Après cela, réglez simplement scrollView height sur numberOfItens * heightOfItem.

Pour découvrir la hauteur d'un article, procédez comme suit:

View item = adapter.getView(0, null, scrollView);
item.measure(0, 0);
int heightOfItem = item.getMeasuredHeight();

Pour définir la hauteur, procédez comme suit:

// if the scrollView already has a layoutParams:
scrollView.getLayoutParams().height = heightOfItem * numberOfItens;
// or
// if the layoutParams is null, then create a new one.
scrollView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, heightOfItem * numberOfItens));
4
Derzu

Ma vue personnalisée MaxHeightScrollView

public class MaxHeightScrollView extends ScrollView {
    private int maxHeight;

    public MaxHeightScrollView(Context context) {
        this(context, null);
    }

    public MaxHeightScrollView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MaxHeightScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        TypedArray styledAttrs =
                context.obtainStyledAttributes(attrs, R.styleable.MaxHeightScrollView);
        try {
            maxHeight = styledAttrs.getDimensionPixelSize(R.styleable.MaxHeightScrollView_mhs_maxHeight, 0);
        } finally {
            styledAttrs.recycle();
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (maxHeight > 0) {
            heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST);
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

style.xml

<declare-styleable name="MaxHeightScrollView">
    <attr name="mhs_maxHeight" format="dimension" />
</declare-styleable>

tilisation

<....MaxHeightScrollView
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    app:mhs_maxHeight="100dp"
    >

    ...

</....MaxHeightScrollView>
3
Phan Van Linh

Avez-vous essayé d'utiliser le valeur layout_weight ? Si vous en définissez une sur une valeur supérieure à 0, la vue sera étendue à l'espace disponible restant.

Si vous aviez plusieurs vues à étirer, la valeur deviendra un poids entre elles.

Ainsi, si vous avez deux vues définies avec une valeur layout_weight de 1, elles s’étireront toutes les deux pour remplir l’espace mais elles s’étireront toutes deux à la même quantité d’espace. Si vous définissez l'une d'elles sur la valeur 2, le résultat sera deux fois plus étendu que celui de l'autre vue.

Quelques informations supplémentaires sont énumérées ici dans Linear Layout.

1
Bryan Denny

Enroulez votre ScrollView autour de votre un simple LinearLayout avec layout_height = "max_height", cela fera un travail parfait. En fait, j'ai ce code en production des 5 dernières années avec zéro numéro.

<LinearLayout
        Android:id="@+id/subsParent"
        Android:layout_width="match_parent"
        Android:layout_height="150dp"
        Android:gravity="bottom|center_horizontal"
        Android:orientation="vertical">

        <ScrollView
            Android:id="@+id/subsScroll"
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:layout_marginBottom="10dp"
            Android:layout_marginEnd="15dp"
            Android:layout_marginStart="15dp">

            <TextView
                Android:id="@+id/subsTv"
                Android:layout_width="wrap_content"
                Android:layout_height="wrap_content"
                Android:text="@string/longText"
                Android:visibility="visible" />

        </ScrollView>
    </LinearLayout>
1
Sai Kiran

Si quelqu'un envisage d'utiliser la valeur exacte pour LayoutParams, par exemple.

setLayoutParams(new LayoutParams(Y, X );

N'oubliez pas de prendre en compte la densité de l'affichage de l'appareil, sinon vous pourriez avoir un comportement très étrange sur différents appareils. Par exemple:

Display display = getWindowManager().getDefaultDisplay();
DisplayMetrics d = new DisplayMetrics();
display.getMetrics(d);
setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, (int)(50*d.density) ));

Comme nous le savons, les appareils fonctionnant sous Android peuvent avoir différentes tailles d’écran. Comme nous le savons plus en détail, les vues doivent s’ajuster de manière dynamique et devenir l’espace approprié.

Si vous définissez une hauteur maximale, vous pouvez forcer la vue à ne pas disposer de suffisamment d'espace ou à moins d'espace. Je sais que parfois, il semble être pratiquement de définir une hauteur maximale. Mais si la résolution change radicalement et si!, La vue, qui a une hauteur maximale, n’apparaîtra pas appropriée.

je pense qu'il n'y a pas de moyen approprié de faire exactement la mise en page que vous voulez. Je vous recommanderais de réfléchir à votre mise en page en utilisant des gestionnaires de mise en page et des mécanismes relatifs. Je ne sais pas ce que vous essayez d'atteindre, mais cela me semble un peu étrange qu'une liste ne contienne que trois éléments, puis que l'utilisateur doit faire défiler l'écran.

btw. minHeight n'est pas garanti (et ne devrait peut-être pas exister non plus). il peut être avantageux de forcer la visibilité des éléments, tandis que les autres éléments relatifs deviennent plus petits.

1
Diego Frehner

D'abord obtenir la hauteur de l'élément en pixels

View rowItem = adapter.getView(0, null, scrollView);   
rowItem.measure(0, 0);    
int heightOfItem = rowItem.getMeasuredHeight();

alors simplement

Display display = getWindowManager().getDefaultDisplay();    
DisplayMetrics displayMetrics = new DisplayMetrics();    
display.getMetrics(displayMetrics);    
scrollView.getLayoutParams().height = (int)((heightOfItem * 3)*displayMetrics .density);
0
Ibrahim Khaled

je pense que vous pouvez définir la hauteur au moment de l'exécution pour 1 élément seulement scrollView.setHeight(200px), pour 2 éléments scrollView.setheight(400px) pendant 3 ou plus scrollView.setHeight(600px)

0
Yayo28

si vous voulez créer une liste déroulante ou une liste déroulante, cliquez sur RelativeLayout avec les options topview et bottomview pour le haut et le bas:

<ScrollView
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:layout_above="@+id/topview"
    Android:layout_below="@+id/bottomview" >
0

J'ai une réponse ici:

https://stackoverflow.com/a/29178364/1148784

Créez simplement une nouvelle classe qui étend ScrollView et remplacez sa méthode onMeasure.

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (maxHeight > 0){
            int hSize = MeasureSpec.getSize(heightMeasureSpec);
            int hMode = MeasureSpec.getMode(heightMeasureSpec);

            switch (hMode){
                case MeasureSpec.AT_MOST:
                    heightMeasureSpec = MeasureSpec.makeMeasureSpec(Math.min(hSize, maxHeight), MeasureSpec.AT_MOST);
                    break;
                case MeasureSpec.UNSPECIFIED:
                    heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST);
                    break;
                case MeasureSpec.EXACTLY:
                    heightMeasureSpec = MeasureSpec.makeMeasureSpec(Math.min(hSize, maxHeight), MeasureSpec.EXACTLY);
                    break;
            }
        }

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
0
babay