Je voudrais que les éléments de mon GridView
soient carrés. Il y a 2 colonnes et la largeur des éléments est fill_parent
(par exemple, ils prennent autant d’espace horizontal que possible. Les éléments sont des vues personnalisées).
Comment faire en sorte que la hauteur des éléments soit égale à leur largeur variable?
Il existe une solution plus simple lorsque les colonnes GridView sont étirées. Il suffit de remplacer le onMeasure de la disposition de l’élément GridView par …
@Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, widthMeasureSpec); }
Ou si vous voulez étendre une vue, faites simplement quelque chose de très simple comme:
public class SquareImageView extends ImageView { public SquareImageView(final Context context) { super(context); } public SquareImageView(final Context context, final AtsortingbuteSet attrs) { super(context, attrs); } public SquareImageView(final Context context, final AtsortingbuteSet attrs, final int defStyle) { super(context, attrs, defStyle); } @Override protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { final int width = getDefaultSize(getSuggestedMinimumWidth(),widthMeasureSpec); setMeasuredDimension(width, width); } @Override protected void onSizeChanged(final int w, final int h, final int oldw, final int oldh) { super.onSizeChanged(w, w, oldw, oldh); } }
Il convient de noter que super.onMeasure()
n’est pas nécessaire. onMeasured
condition onMeasured
est que vous devez appeler setMeasuredDimension
.
Je ne suis pas sûr que cela soit possible avec les widgets actuels. Votre meilleur pari pourrait être de mettre votre vue personnalisée dans un “SquareView” personnalisé. Cette vue pourrait simplement contenir une vue enfant et forcer la hauteur à égaler la largeur lorsque sa méthode onLayout est appelée.
Je n’ai jamais essayé de faire quelque chose comme ça, mais je pense que ça ne devrait pas être trop difficile. Une solution alternative (et peut-être légèrement plus simple) pourrait consister à sous-classer la disposition racine de votre vue personnalisée (comme, si c’est un LinearLayout, créer un SquareLinearLayout), et l’utiliser plutôt comme un conteneur.
edit: Voici une implémentation de base qui semble fonctionner pour moi:
package com.mantano.widget; import android.content.Context; import android.util.AtsortingbuteSet; import android.view.View; import android.view.ViewGroup; public class SquareView extends ViewGroup { public SquareView(Context context, AtsortingbuteSet attrs) { super(context, attrs); } @Override protected void onLayout(boolean changed, int l, int u, int r, int d) { getChildAt(0).layout(0, 0, rl, du); // Layout with max size } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { View child = getChildAt(0); child.measure(widthMeasureSpec, widthMeasureSpec); int width = resolveSize(child.getMeasuredWidth(), widthMeasureSpec); child.measure(width, width); // 2nd pass with the correct size setMeasuredDimension(width, width); } }
Il est conçu pour avoir un enfant unique, mais j’ai ignoré tous les contrôles pour des raisons de simplicité. L’idée de base est de mesurer l’enfant avec les parameters width / height définis par GridView (dans mon cas, il utilise numColumns = 4 pour calculer la largeur), puis effectue une seconde passe avec les dimensions finales, height = width. .. La mise en page est simplement une présentation simple, qui met en page l’enfant unique à (0, 0) avec les dimensions souhaitées (droite-gauche, bas).
Et voici le XML utilisé pour les éléments GridView:
J’ai utilisé un LinearLayout dans le SquareView pour lui faire gérer toutes les possibilités de gravitation, les marges, etc.
Je ne suis pas sûr que ce widget réagisse bien à l’orientation et aux changements de dimension, mais il semble fonctionner correctement.
Il est assez facile d’obtenir le carré de la grid.
Dans votre méthode “GetView” de votre adaptateur de grid, procédez comme suit:
@Override public View getView(int position, View convertView, ViewGroup parent) { GridView grid = (GridView)parent; int size = grid.getRequestedColumnWidth(); TextView text = new TextView(getContext()); text.setLayoutParams(new GridView.LayoutParams(size, size)); // Whatever else you need to set on your view return text; }
Je ne sais pas si c’est le meilleur moyen, mais je réalise cela en faisant en sorte que mon affichage personnalisé remplace OnSizeChanged de cette façon:
@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); if (getLayoutParams() != null && w != h) { getLayoutParams().height = w; setLayoutParams(getLayoutParams()); } }
J’utilise cette vue personnalisée dans un LinearLayout et un GridView et dans les deux, elle montre un carré!
Cela a fonctionné pour moi!
Si vous êtes comme moi et que vous ne pouvez pas utiliser getRequestedColumnWidth () car votre minSdk est inférieur à 16, je suggère cette option.
dans votre fragment:
DisplayMesortingcs dm = new DisplayMesortingcs(); getActivity().getWindowManager().getDefaultDisplay().getMesortingcs(dm); int size = dm.widthPixels / nbColumns; CustomAdapter adapter = new CustomAdapter(list, size, getActivity());
dans votre adaptateur (dans getView (int position, View convertView, parent du ViewGroup))
v.setLayoutParams(new GridView.LayoutParams(GridView.AUTO_FIT, size));
fragment.xml:
custom_item.xml: (par exemple)
J’espère que ça va aider quelqu’un!
Si vous définissez un nombre statique de colonnes dans le fichier XML, vous pouvez prendre la largeur de la vue et la diviser par le nombre de colonnes.
Si vous utilisez auto_fit
il sera difficile de compter le nombre de colonnes (il n’y a pas de méthode getColumnCount ()), mais cette question devrait vous aider.
c’est le code que j’utilise dans la getView(...)
de l’adaptateur avec un nombre fixe de colonnes:
item_side = mFragment.holder.grid.getWidth() / N_COL; v.getLayoutParams().height = item_side; v.getLayoutParams().width = item_side;