GridLayout (pas GridView) comment étirer uniformément tous les enfants

Je veux avoir une grid 2×2 avec des boutons à l’intérieur. Ceci est seulement ICS donc j’essaye d’utiliser le nouveau GridLayout donné.

Voici le XML de ma mise en page:

  

Le problème est que mes vues ne s’étendent pas uniformément pour chaque ligne. Cela crée beaucoup d’espace à droite de mon GridLayout.

J’ai essayé de paramétrer layout_gravity="fill_horizontal" mais cela ne s’applique qu’à la dernière vue de la ligne. Cela signifie que la cellule 1 s’étend complètement pour donner suffisamment d’espace pour la cellule 0.

Réflexions sur la façon de faire face à cela?

MISE À JOUR : Les poids sont pris en charge à partir de l’API 21. Voir la réponse de PaulT pour plus de détails. END UPDATE Il existe des limitations lors de l’utilisation de GridLayout, la citation suivante est extraite de la documentation .

“GridLayout ne prend pas en charge le principe de pondération, tel que défini en poids. En général, il n’est pas possible de configurer un GridLayout pour répartir l’espace excédentaire dans des proportions non sortingviales entre plusieurs lignes ou colonnes … la dissortingbution d’espace excédentaire dans une ligne ou une colonne; utilisez une sous-vue LinearLayout pour contenir les composants du groupe de cellules associé. ”

Voici un petit exemple qui utilise les sous-vues LinearLayout. (J’ai utilisé Space Views qui occupe une zone inutilisée et pousse les boutons dans la position souhaitée.)

                  

À partir de l’API 21, la notion de poids a été ajoutée à GridLayout. Pour prendre en charge des périphériques Android plus anciens, vous pouvez utiliser GridLayout à partir de la bibliothèque de support v7.

Le XML suivant donne un exemple de la façon dont vous pouvez utiliser des pondérations pour remplir la largeur de l’écran.

        

entrer la description de l'image ici

Appcompat21 GridLayout a les poids des colonnes et des lignes qui peuvent être utilisés comme ci-dessous pour créer de manière uniforme chaque élément de grid dans le gridlayout comme l’image ci-dessus.

   ... ... ... 

Vous pouvez définir la largeur de chaque enfant dynamicment:

 GridLayout.LayoutParams params = (GridLayout.LayoutParams) child.getLayoutParams(); params.width = (parent.getWidth()/parent.getColumnCount()) -params.rightMargin - params.leftMargin; child.setLayoutParams(params); 

À partir de la bibliothèque de support API 21 sans v7 avec ScrollView:

entrer la description de l'image ici

XML:

          

Essayez d’append ce qui suit à votre spécification GridLayout. Cela devrait fonctionner.

 android:useDefaultMargins="true" 

C’est la bonne réponse

        

Dans mon cas, j’ajoutais les boutons de manière dynamic, ma solution nécessitait donc une partie XML et une partie Java. J’ai dû trouver et mélanger des solutions à partir de plusieurs endroits différents et j’ai pensé que je le partagerais ici pour que quelqu’un d’autre à la recherche de la solution similaire puisse le trouver utile.

Première partie de mon fichier de mise en page XML …

   

grid:useDefaultMargins="true" n’est pas requirejs mais j’ai ajouté parce que cela me paraissait meilleur, vous pouvez appliquer d’autres effets visuels (par exemple, le remplissage) comme mentionné dans certaines réponses ici. Maintenant, pour les boutons, je dois les append dynamicment. Voici la partie Java de mon code pour créer ces boutons, je n’inclus que les lignes liées à ce contexte. Supposons que je myOptions créer des boutons à partir de myOptions disponibles pour mon code et que je ne copie pas non plus le code OnClickListener.

 import android.support.v7.widget.GridLayout; //Reference to Library public class myFragment extends Fragment{ GridLayout gl_Options; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { gl_AmountOptions = (GridLayout)view.findViewById( R.id.gl_AmountOptions ); ... gl_Options.removeAllViews(); // Remove all existing views gl_AmountOptions.setColumnCount( myOptions.length <= 9 ? 3: 4 ); // Set appropriate number of columns for( String opt : myOptions ) { GridLayout.LayoutParams lParams = new GridLayout.LayoutParams( GridLayout.spec( GridLayout.UNDEFINED, 1f), GridLayout.spec( GridLayout.UNDEFINED, 1f)); // The above defines LayoutParameters as not specified Column and Row with grid:layout_columnWeight="1" and grid:layout_rowWeight="1" lParams.width = 0; // Setting width to "0dp" so weight is applied instead Button b = new Button(this.getContext()); b.setText( opt ); b.setLayoutParams(lParams); b.setOnClickListener( myClickListener ); gl_Options.addView( b ); } } } 

Comme nous utilisons GridLayout à partir de la bibliothèque de support et non avec le GridLayout standard, nous devons en YourProject.grade fichier YourProject.grade .

 dependencies { comstack 'com.android.support:appcompat-v7:23.4.0' ... comstack 'com.android.support:gridlayout-v7:23.4.0' } 

J’ai finalement trouvé la solution. Comme l’a dit Rotemmiz, il faut le faire dynamicment par la suite. Ce code étend les boutons pour remplir la vue horizontalement, mais la même chose peut être faite verticalement.

 public void fillview(android.support.v7.widget.GridLayout gl) { Button buttontemp; //Stretch buttons int idealChildWidth = (int) ((gl.getWidth()-20*gl.getColumnCount())/gl.getColumnCount()); for( int i=0; i< gl.getChildCount();i++) { buttontemp = (Button) gl.getChildAt(i); buttontemp.setWidth(idealChildWidth); } } 

(Le 20 est pour le remplissage interne et externe et les marges. Cela pourrait être fait plus universellement, mais c'est beaucoup plus propre)

Ensuite, il peut être appelé comme ceci:

  android.support.v7.widget.GridLayout gl = (android.support.v7.widget.GridLayout)findViewById(R.id.buttongrid); ViewTreeObserver vto = gl.getViewTreeObserver(); vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {@Override public void onGlobalLayout() { android.support.v7.widget.GridLayout gl = (android.support.v7.widget.GridLayout) findViewById(R.id.buttongrid); fillview(gl); ViewTreeObserver obs = gl.getViewTreeObserver(); obs.removeGlobalOnLayoutListener(this); }}); 

Cela doit être fait avec un observateur car nous devons attendre que la vue soit dessinée avant d'appeler les vues.

Vous pouvez rendre cela plus rapide en remplaçant la méthode ViewGroup onLayout. Ceci est ma solution universelle:

 package your.app.package; import android.content.Context; import android.view.ViewGroup; public class GridLayout extends ViewGroup { public GridLayout(Context context) { super(context); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { final int columns = 2;//edit this if you need different grid final int rows = 2; int children = getChildCount(); if (children != columns * rows) throw new IllegalStateException("GridLayout must have " + columns * rows + " children"); int width = getWidth(); int height = getHeight(); int viewWidth = width / columns; int viewHeight = height / rows; int rowIndex = 0; int columnIndex = 0; for (int i = 0; i < children; i++) { getChildAt(i).layout(viewWidth * columnIndex, viewHeight * rowIndex, viewWidth * columnIndex + viewWidth, viewHeight * rowIndex + viewHeight); columnIndex++; if (columnIndex == columns) { columnIndex = 0; rowIndex++; } } } } 

EDIT: N'oubliez pas match_parent pour les enfants!

 android:layout_width="match_parent" android:layout_height="match_parent" 

La meilleure solution que je pourrais trouver consiste à utiliser une disposition linéaire (horizontale) pour chaque ligne souhaitée et à y affecter la largeur du bouton (cellule) à 0dp et le poids à 1. Pour chacune des dispositions linéaires (lignes), atsortingbuez la hauteur à 0dp et le poids à 1. Trouvez le code ci-dessous- android également: layout_gravity = “center_vertical” est utilisé pour aligner les boutons dans une ligne au cas où ils contiennent du texte de longueur variable. Utilisez 0dp et pesez-le comme un truc bien soigné mais pas si bien connu.

           

Je voulais avoir une table centrée avec les étiquettes alignées à droite et les valeurs alignées. L’espace supplémentaire devrait être autour de la table. Après beaucoup d’expérimentation et sans suivre ce que la documentation disait, je devais faire quelque chose qui fonctionne. Voici ce que j’ai fait:

        

Cela semble fonctionner mais le GridLayout affiche le message:

“Cette mise en page GridLayout ou son parent LinearLayout est inutile”

Pas sûr pourquoi il est “inutile” quand ça marche pour moi.

Je ne sais pas pourquoi cela fonctionne ou si c’est une bonne idée, mais si vous l’essayez et pouvez vous faire une meilleure idée, apporter de petites améliorations ou expliquer pourquoi cela fonctionne (ou ne fonctionnera pas), j’apprécierais les commentaires.

Merci.

C’est une question assez ancienne, mais qui intéresse évidemment beaucoup de gens. Pour une mise en page simple de 4 boutons comme celui-ci, il semble que TableLayout soit le moyen le plus simple d’obtenir le résultat souhaité.

Voici un exemple de code montrant les 2 premières lignes d’un tableau avec 6 colonnes couvrant la largeur de son parent. LinearLayout et ImageView dans chaque cellule permettent d’activer et de désactiver une image dans la cellule tout en conservant la couleur de la cellule.

                                           

Ancienne question, mais je voulais append ma solution. J’ai créé une “disposition de grid linéaire” qui simule une grid mais en utilisant des dispositions linéaires nestedes. Cela lui permet de s’étirer pour remplir l’espace.

http://zerocredibility.wordpress.com/2014/12/18/linear-grid-layout/

Vous voilà :

 Button button = new Button(this); // weight = 1f , gravity = GridLayout.FILL GridLayout.LayoutParams param= new GridLayout.LayoutParams(GridLayout.spec( GridLayout.UNDEFINED,GridLayout.FILL,1f), GridLayout.spec(GridLayout.UNDEFINED,GridLayout.FILL,1f)); // Layout_height = 0 ,Layout_weight = 0 params.height =0; params.width = 0; button.setLayoutParams(param); 

Voici ce que j’ai fait et je suis heureux de dire que cela a fonctionné pour moi. Je voulais aussi une grid d’éléments 2×2, 3×3, etc. pour couvrir tout l’écran. Les Gridlayouts n’adhèrent pas à la largeur de l’écran. LinearLayouts fonctionne, mais vous ne pouvez pas utiliser les poids nesteds.

La meilleure option pour moi était d’utiliser Fragments J’ai utilisé ce tutoriel pour commencer avec ce que je voulais faire.

Voici un code:

Activité principale:

 public class GridHolderActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main_6); } } 

activity_main_6 XML (gonfle 3 fragments)

      

Agencement de fragment de base

     

Fragment Class (gère uniquement l’initialisation d’une vue personnalisée) gonfle 2 tuiles par fragment

 public class TwoHorizontalGridFragment extends Fragment { private View rootView; private ImageQueue imageQueue1; private ImageQueue imageQueue2; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { /** * Inflate the layout for this fragment */ rootView = inflater.inflate( R.layout.two_horiz, container, false); return rootView; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); imageQueue1 = (ImageQueue)rootView.findViewById(R.id.img1); imageQueue2 = (ImageQueue)rootView.findViewById(R.id.img2); imageQueue1.updateFiles(); imageQueue2.updateFiles(); } 

}

C’est tout!

Ceci est un travail étrange pour utiliser des poids nesteds, essentiellement. Cela me donne une grid 2×3 parfaite qui remplit tout l’écran de ma tablette de 10 pouces et de mon ADN de droïde HTC. Faites-moi savoir comment ça se passe pour vous!