2016-02-24 1 views
6

Je voudrais utiliser un GridLayout (pas GridView) comme planche pour un jeu comme les échecs ou les dames. Comme je suis un peu réticent à utiliser un fichier XML avec 64 enfants View, j'ai essayé de les ajouter par programmation.Comment définir layout_columnWeight pour un enfant GridLayout lorsqu'il est ajouté par programme?

Pour garder les choses simples, j'ai commencé à utiliser TextView comme enfant View pour le GridLayout.

Mon problème est que les View ne sont pas répartis uniformément, et que je ne sais pas comment obtenir une distribution régulière dans mon code java. Il n'y a pas de méthode comme "setWeight()" pour le réglage layout_columnWeight et layout_rowWeight.

À l'heure actuelle, ceci est mon activity_dynamic_grid_layout.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent"> 

<ImageView 
    android:layout_width="match_parent" 
    android:layout_height="80dp" 
    android:id="@+id/ivLogo" 
    android:background="#ff0000" 
    android:layout_alignParentTop="true" 
    android:layout_alignParentLeft="true" 
    android:layout_alignParentStart="true"/> 

<android.support.v7.widget.GridLayout 
    android:id="@+id/grid_layout" 
    android:background="#004080" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:layout_below="@+id/ivLogo" 
    android:layout_alignParentLeft="true" 
    android:layout_alignParentStart="true" 
    android:layout_marginTop="36dp"> 

</android.support.v7.widget.GridLayout> 

Je me suis fixé la largeur et la hauteur GridLayoutmatch_parent ici, mais je les changer lors de l'exécution en utilisant un ViewTreeObserver.OnPreDrawListener pour obtenir un tableau carré. Cela fonctionne, l'arrière-plan coloré montre un espace carré comme prévu.

Mon onCreate()

@Override 
protected void onCreate(Bundle savedInstanceState) 
{ 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_dynamic_grid_layout); 

    GridLayout gl = (GridLayout) findViewById(R.id.grid_layout); 
    gl.setColumnCount(8); 
    gl.setRowCount(8); 

    for(int i=0; i<gl.getRowCount(); i++) 
    { 
     GridLayout.Spec rowSpec = GridLayout.spec(i, 1, GridLayout.FILL); 

     for(int j=0;j<gl.getColumnCount();j++) 
     { 
      GridLayout.Spec colSpec = GridLayout.spec(j,1, GridLayout.FILL); 

      TextView tvChild = new TextView(this); 
      tvChild.setText("[ " + i + " | " + j + " ]"); 
      tvChild.setTextSize(18f); 
      tvChild.setTextColor(Color.WHITE); 
      tvChild.setGravity(Gravity.CENTER); 

      GridLayout.LayoutParams myGLP = new GridLayout.LayoutParams(); 
      myGLP.rowSpec = rowSpec; 
      myGLP.columnSpec = colSpec; 

      gl.addView(tvChild, myGLP); 
     } 
    } 

    final View rootView = findViewById(R.id.dynamic_root); 

    rootView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() 
    { 
     @Override 
     public boolean onPreDraw() 
     { 
      int w = rootView.getMeasuredWidth(); 
      int h = rootView.getMeasuredHeight(); 
      int min = Math.min(w, h); 

      ViewGroup.LayoutParams lp = gl.getLayoutParams(); 
      lp.width = min - min % 9; 
      lp.height = lp.width; 
      gl.setLayoutParams(lp); 

      rootView.getViewTreeObserver().removeOnPreDrawListener(this); 

      return true; 
     } 
    }); 
} 

Ce que j'ai déjà essayé:

je mets un TextView enfant dans le fichier de mise en page et a essayé de copier le layout_columnWeight et layout_rowWeight de son GridLayout.LayoutParams :

<android.support.v7.widget.GridLayout 
...> 
    <TextView 
     android:id="@+id/clone_my_params" 
     android:text="[ 0 | 0 ]" 
     android:textColor="#ffffff" 
     android:textSize="18sp" 
     app:layout_column="0" 
     app:layout_row="0" 
     app:layout_columnWeight="1" 
     app:layout_rowWeight="1" 
    /> 
</android.support.v7.widget.GridLayout> 

Code additionnel dans onCreate(), avant la double boucle:

TextView v = (TextView)gl.findViewById(R.id.clone_my_params); 
v.setGravity(Gravity.CENTER); 
GridLayout.LayoutParams gridLayoutParamsToCopy = new GridLayout.LayoutParams(v.getLayoutParams()); 

intérieur de la boucle, je sautée (i, j) = (0,0) et a changé

GridLayout.LayoutParams myGLP = new GridLayout.LayoutParams(); 

à

GridLayout.LayoutParams myGLP = new GridLayout.LayoutParams(gridLayoutParamsToCopy); 

Avant le changement, tous les éléments étaient dans le coin supérieur gauche, l'espace excédentaire était donné à la dernière ligne/colonne. Après le changement, la première rangée/colonne avait l'espace excédentaire, aucun changement pour les autres éléments. L'appel gl.invalidate() et/ou gl.requestLayout() après que la double boucle n'a eu aucun effet.

Il semble donc que je n'ai pas réussi à définir le poids désiré en utilisant le constructeur de copie.

+0

Tout d'abord, si tout ce que vous voulez est une grille de 8x8 carré, il pourrait être plus facile (et efficace) pour faire une coutume ViewGroup (il est la mise en œuvre serait assez simple). Deuxièmement, ne devriez-vous pas utiliser une méthode spec qui reçoit un flottant comme http://developer.android.com/reference/android/widget/GridLayout.html#spec(int, int, android.widget.GridLayout.Alignment, float) pour les Spec? – Luksprog

+0

@Luksprog - sur le ViewGroup personnalisé: J'ai un prototype du jeu avec une vue personnalisée comme un plateau de jeu, remplaçant "onDraw()", et maintenant j'expérimente avec GridView ainsi que GridLayout. Je suis plutôt nouveau dans le développement Android et j'essaie de déterminer quelle version sera la meilleure du point de vue des performances. A propos de la méthode: OK, c'est ce qui se passe si le niveau de l'API est fixé à 14 - j'ai utilisé spec (int start, int size) et seulement maintenant remarqué une spécification (int start, float weight). Je pense que mon soutien GridLayout l'a aussi, peut-être que c'est ce qui me manquait. Merci pour l'indice! – 0X0nosugar

+0

@Luksprog - mission accomplie :) L'ajout de "1f" comme dernier paramètre dans la spécification() a fait l'affaire. Voudriez-vous l'écrire comme une réponse pour que je puisse changer de sujet? – 0X0nosugar

Répondre

1

Pour définir le poids sur les enfants de votre Gridlayout, utilisez l'une des méthodes spec() (comme cette one) qui prend une valeur flottante.

Une autre approche serait de créer une vue personnalisée (dans ce cas, vous devrez dessiner manuellement les pièces) ou un ViewGroup personnalisé (dans ce cas, le ViewGroup personnalisé se chargera du positionnement des pièces, être approprié si vous prévoyez d'avoir des hiérarchies de vues plus complexes qu'un simple TextView).

+0

merci encore une fois, et juste une question: si je suis en train d'étendre ImageButton pour les pièces de jeu, et que vous souhaitez profiter des animations View et ViewGroup, puis-je utiliser un GridView ou un GridLayout? – 0X0nosugar

+1

@ 0X0nosugar Peu importe. L'extension depuis ImageButton ou l'utilisation de ViewGroup ne modifie pas les options d'animation des vues, que ce soit directement ou via des transitions de mise en page. Vous devriez utiliser un GridLayout uniquement parce que GridView est beaucoup mieux adapté pour d'autres cas. – Luksprog

1

-Voici vous êtes! :>

Button button = new Button(this); 
GridLayout.LayoutParams param= new GridLayout.LayoutParams(GridLayout.spec(
      GridLayout.UNDEFINED,GridLayout.FILL,1f), 
      GridLayout.spec(GridLayout.UNDEFINED,GridLayout.FILL,1f)); 
param.height =0;                           
param.width = 0; 
button.setLayoutParams(param); 
+0

Veuillez expliquer (modifier votre réponse) comment votre code résout le problème. Cela pourrait ne pas être clair à partir du code lui-même. –

+0

Testé avec trois émulateurs différents (Android 5 à 7, téléphone et tablette, hdpi et mdpi): ça marche, donc merci :) – 0X0nosugar