Comment dimensionner une vue en fonction de la taille de sa disposition parente. Par exemple, j'ai un RelativeLayout
qui remplit tout l'écran et je veux une vue enfant, disons un ImageView
, pour occuper toute la hauteur et la moitié de la largeur?
J'ai essayé de tout annuler sur onMeasure
, onLayout
, onSizeChanged
, etc., et je ne pouvais pas le faire fonctionner ....
Je ne sais pas si quelqu'un lit encore ce fil ou non, mais la solution de Jeff ne vous mènera qu'à la moitié (littéralement). Ce que son onMeasure va faire, c'est afficher la moitié de l'image dans la moitié du parent. Le problème est que l'appel de super.onMeasure avant le setMeasuredDimension
mesurera tous les enfants de la vue en fonction de la taille d'origine, puis coupera la vue en deux lorsque le setMeasuredDimension
le redimensionnera.
Au lieu de cela, vous devez appeler setMeasuredDimension
(comme requis pour une substitution onMeasure) et fournissez un nouveau LayoutParams
pour votre vue, alors appelez super.onMeasure
. Rappelez-vous que vos LayoutParams
sont dérivés du type de parent de votre vue, et non 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
, c’est si le parent est un AbsoluteLayout
(ce qui est obsolète mais reste parfois utile).
Vous pouvez résoudre ce problème en créant une vue personnalisée et en remplaçant la méthode onMeasure (). Si vous utilisez toujours "fill_parent" pour layout_width dans votre fichier xml, le paramètre widthMeasureSpec transmis à la méthode onMeasusre () doit 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 ça:
<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 perdre son temps à régler vous-même les dimensions mesurées. En fait, il y a un peu de négociation entre les vues parent et enfant et vous ne voulez pas réécrire tout cela code .
Ce que vous pouvez faire, cependant, est de modifier les mesures, puis d'appeler super avec elles. 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 présentation et une vue sur XML, vous pouvez spécifier la largeur et la hauteur de la présentation d’une vue soit en tant que contenu renvoyé, soit en remplissant le parent. Prendre la moitié de la surface 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 le même poids à deux choses signifie qu'elles vont s'étirer pour occuper la même proportion de l'écran. Pour plus d'informations sur les dispositions, voir les documents de développement.
Je crois que approche XML de Mayras peut être soigné. Cependant, il est possible de le rendre plus précis, avec une seule vue en réglant le weightSum. 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 cela, vous pouvez utiliser n’importe quel poids, 0.6 par exemple (et le centrage) est le poids que j’aime utiliser pour les boutons.
Essaye ça
int parentWidth = ((parentViewType)childView.getParent()).getWidth();
int parentHeight = ((parentViewType)childView.getParent()).getHeight();
alors vous pouvez utiliser LinearLayout.LayoutParams pour définir les paramètres de chileView
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(childWidth,childLength);
childView.setLayoutParams(params);
Vous pouvez maintenant utiliser PercentRelativeLayout. Boom! Problème résolu.
Si l'autre côté est vide. Le moyen le plus simple consiste à ajouter une vue vide (une disposition linéaire, par exemple), puis à définir les largeurs des deux vues sur fill_parent et leur poids à 1.
Cela fonctionne dans un LinearLayout ...
Roman, si vous voulez faire votre mise en page dans Java (descendant de ViewGroup)), c’est possible. Le truc, c’est que vous devez implémenter les méthodes onMeasure et onLayout. Le onMeasure est appelé en premier et vous devez "mesurer" la sous-vue (en la dimensionnant effectivement à la valeur souhaitée). Vous devez redimensionner à nouveau dans l'appel onLayout. Si vous ne parvenez pas à effectuer cette séquence ou à appeler setMeasuredDimension () à la fin de votre onMeasure code, vous n'obtiendrez aucun résultat. Pourquoi cela est-il conçu de manière si compliquée et si fragile me dépasse-t-il?.
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>