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....
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).
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>
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);
}
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.
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.
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);
vous pouvez maintenant utiliser le pourcentage RelativeLayout. Boom! Le problème est résolu.
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.
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...
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>