Comment dimensionner une vue Android en fonction des dimensions de ses parents

Comment puis-je dimensionner une vue en fonction de la taille de sa disposition parente. Par exemple, j'ai un RelativeLayout qui remplit le plein écran, et je veux une vue d'enfant , dire un ImageView , pour prendre toute la hauteur, et la moitié de la largeur?

j'ai essayé de passer outre onMeasure , onLayout , onSizeChanged , etc et je n'ai pas pu le faire fonctionner....

98
demandé sur Mike Baxter 2010-01-29 04:30:46

10 réponses

Je ne sais pas si quelqu'un est encore en train de lire ce fil ou pas, mais la solution de Jeff ne vous mènera qu'à mi-chemin (un peu littéralement). Ce que son onMeasure va faire est d'afficher la moitié de l'image dans la moitié du parent. Le problème, c'est que l'appel à super.onMeasure avant le setMeasuredDimension permettra de mesurer tous les enfants dans la vue en fonction de la taille originale, puis il suffit de couper la vue de moitié lorsque le setMeasuredDimension la redimensionne.

à la place, vous devez appeler setMeasuredDimension (comme requis pour un outrepassement onMeasure) et fournir un nouveau LayoutParams pour votre vue, puis appel super.onMeasure . Rappelez-vous, votre LayoutParams est dérivé du type parent de votre vue, pas du type de votre vue.

@Override 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
   int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
   int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
   this.setMeasuredDimension(parentWidth/2, parentHeight);
   this.setLayoutParams(new *ParentLayoutType*.LayoutParams(parentWidth/2,parentHeight));
   super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

je crois que la seule fois où vous aurez des problèmes avec le parent LayoutParams est si le parent est un AbsoluteLayout (qui est déprécié mais encore parfois utile).

122
répondu Vic 2013-07-15 02:08:48

vous pouvez résoudre cela en créant une vue personnalisée et remplacer la méthode onMeasure (). Si vous utilisez toujours "fill_parent" pour layout_width dans votre xml, alors le paramètre widthMeasureSpec qui est passé dans la méthode onMeasusre() devrait contenir la largeur du parent.

public class MyCustomView extends TextView {

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

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
        int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
        this.setMeasuredDimension(parentWidth / 2, parentHeight);
    }
}   

votre XML ressemblerait à quelque chose comme ceci:

<LinearLayout 
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <view
        class="com.company.MyCustomView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>
38
répondu Jeff 2018-10-04 08:56:43

j'ai trouvé qu'il est préférable de ne pas jouer avec le réglage des dimensions mesurées vous-même. Il y a en fait un peu de négociation qui se poursuit entre les points de vue des parents et des enfants et vous ne voulez pas réécrire tout ce code .

ce que vous pouvez faire, cependant, c'est Modifier les measureSpecs, puis appeler super avec eux. Votre vue ne saura jamais qu'elle reçoit un message modifié de son parent et s'occupera de tout pour vous:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
    int myWidth = (int) (parentHeight * 0.5);
    super.onMeasure(MeasureSpec.makeMeasureSpec(myWidth, MeasureSpec.EXACTLY), heightMeasureSpec);
}
25
répondu Phil Kulak 2016-06-17 11:24:42

lorsque vous définissez une mise en page et une vue sur XML, vous pouvez spécifier la largeur et la hauteur de la mise en page d'une vue pour soit être du contenu wrap, soit remplir le parent. Prendre la moitié de la zone est un peu plus difficile, mais si vous aviez quelque chose que vous vouliez sur l'autre moitié, vous pourriez faire quelque chose comme ce qui suit.

   <LinearLayout android:layout_width="fill_parent"
                android:layout_height="fill_parent">
        <ImageView android:layout_height="fill_parent"
                 android:layout_width="0dp"
                 android:layout_weight="1"/>
        <ImageView android:layout_height="fill_parent"
                 android:layout_width="0dp"
                 android:layout_weight="1"/>
   </LinearLayout>

Donner deux choses le même poids signifie qu'ils vont s'étirer pour prendre la même proportion de l'écran. Pour plus d'informations sur les mises en page, voir le dev doc.

15
répondu Cheryl Simon 2010-01-29 18:04:09

je crois que le Mayras XML-approche peut venir en ordonnée. Il est cependant possible de le rendre plus précis, avec une seule vue en réglant le poids. Je n'appellerais plus cela un piratage mais à mon avis l'approche la plus simple:

<LinearLayout android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:weightSum="1">
    <ImageView android:layout_height="fill_parent"
               android:layout_width="0dp"
               android:layout_weight="0.5"/>
</LinearLayout>

comme ceci vous pouvez utiliser n'importe quel poids, 0.6 par exemple (et centrage) est le poids que j'aime utiliser pour les boutons.

9
répondu pinkwerther 2017-05-23 11:47:21

Essayez cette

int parentWidth = ((parentViewType)childView.getParent()).getWidth();
int parentHeight = ((parentViewType)childView.getParent()).getHeight();

alors vous pouvez utiliser LinearLayout.LayoutParams pour le réglage de la chileView paramètres

LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(childWidth,childLength);
childView.setLayoutParams(params);
3
répondu Abhishek Gupta 2015-05-31 20:52:12

vous pouvez maintenant utiliser le pourcentage RelativeLayout. Boom! Le problème est résolu.

2
répondu androidguy 2016-09-13 01:49:16

Roman, si vous voulez faire votre mise en page en code Java (ViewGroup descendant), il est possible. Le truc est que vous devez implémenter à la fois les méthodes onMeasure et onLayout. L'onMeasure est appelée en premier et vous avez besoin de" mesurer " le subview (en l'ajustant à la valeur désirée) là. Vous avez besoin de la taille à nouveau dans l'appel onLayout. Si vous ne parvenez pas à faire cette séquence ou à appeler setMeasuredDimension() à la fin de votre code onMeasure, vous n'obtiendrez pas de résultats. Pourquoi est-ce conçu d'une façon aussi compliquée et fragile est au-delà de moi.

1
répondu Pavel Lahoda 2010-02-10 17:59:08

Si l'autre côté est vide. Je suppose que la manière la plus simple serait d'ajouter une vue vide (par exemple un layout linéaire) puis de définir les largeurs des deux vues pour fill_parent et leurs deux poids à 1.

cela fonctionne dans un délai linéaire...

1
répondu jpm 2016-07-13 09:32:20

c'est quelque chose comme ça:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.company.myapp.ActivityOrFragment"
    android:id="@+id/activity_or_fragment">

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/linearLayoutFirst"
    android:weightSum="100">   <!-- Overall weights sum of children elements -->

    <Spinner
        android:layout_width="0dp"   <!-- It's 0dp because is determined by android:layout_weight -->
        android:layout_weight="50"
        android:layout_height="wrap_content"
        android:id="@+id/spinner" />

</LinearLayout>


<LinearLayout
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:layout_below="@+id/linearLayoutFirst"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:id="@+id/linearLayoutSecond">

    <EditText
        android:layout_height="wrap_content"
        android:layout_width="0dp"
        android:layout_weight="75"
        android:inputType="numberDecimal"
        android:id="@+id/input" />

    <TextView
        android:layout_height="wrap_content"
        android:layout_width="0dp"
        android:layout_weight="25"
        android:id="@+id/result"/>

</LinearLayout>
</RelativeLayout>
0
répondu Mario 2014-10-09 16:29:15