2016-02-24 20 views
6

Chciałbym użyć tablicy GridLayout (nie GridView) do gry w szachy lub warcaby. Ponieważ jestem trochę niechętny do korzystania z pliku xml z 64 dziećmi View s, próbowałem je dodawać programowo.Jak ustawić parametr column_columnWeight dla elementu potomnego GridLayout, gdy jest on dodawany programowo?

Aby wszystko było proste, zacząłem od używania TextView s jako dziecka View s dla .

Mój problem polega na tym, że View s nie są rozmieszczone równomiernie, a ja nie wiem, jak uzyskać równomierną dystrybucję w moim kodzie java. Nie ma metody takiej jak "setWeight()" dla ustawienia layout_columnWeight i layout_rowWeight.

Obecnie jest to mój 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> 

mam ustawić szerokość i wysokość GridLayout do match_parent tutaj, ale ja ich zmiany w czasie wykonywania przy użyciu ViewTreeObserver.OnPreDrawListener w celu zdobądź kwadratową planszę. To działa, kolorowe tło pokazuje kwadratową spację zgodnie z przeznaczeniem.

Moja 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; 
     } 
    }); 
} 

Co Próbowałem już:

kładę jeden TextView dziecko w pliku layoutu i próbował skopiować layout_columnWeight i layout_rowWeight z jego 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> 

Kod dodatkowy w onCreate() przed podwójnej pętli:

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

Wewnątrz pętli pominąłem (i, j) = (0,0) i zmienił

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

do

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

Przed zmianą wszystkie elementy znajdowały się w lewym górnym rogu, nadmiar miejsca był nadawany do ostatniego wiersza/kolumny. Po zmianie pierwszy wiersz/kolumna miał nadmiar przestrzeni, bez zmian dla pozostałych elementów.

Wywołanie gl.invalidate() i/lub gl.requestLayout() po tym, jak podwójna pętla nie przyniosła efektu.

Wygląda na to, że nie udało mi się ustawić żądanej wagi za pomocą konstruktora kopii.

+0

Przede wszystkim, jeśli chcesz to kwadrat siatki 8x8 może być łatwiej (i skuteczny), aby zwyczaj ViewGroup (jest wdrożenie byłoby dość proste). Po drugie, czy nie powinieneś używać metody spec, która odbiera float jak http://developer.android.com/reference/android/widget/GridLayout.html#spec(int, int, android.widget.GridLayout.Alignment, float) dla specyfikacji? – Luksprog

+0

@Luksprog - o niestandardowej ViewGroup: Mam prototyp gry z niestandardowym widokiem jako gameboard, przesłaniając "onDraw()", a teraz eksperymentuję z GridView oraz GridLayout. Jestem raczej nowy w rozwoju Androida i staram się dowiedzieć, która wersja będzie najlepsza z punktu widzenia wydajności. O metodzie: OK, tak się dzieje, jeśli poziom API ustawiony jest na 14 - użyłem spec (int start, int size) i dopiero teraz zauważyłem, że istnieje spec (int start, float weight). Myślę, że moje wsparcie GridLayout też je ma, może tego właśnie mi brakowało. Dzięki za podpowiedź! – 0X0nosugar

+0

@Luksprog - misja zakończona :) Dodanie "1f" jako ostatniego parametru w spec() zmyśliło. Czy chciałbyś zapisać to jako odpowiedź, abym mógł przegłosować? – 0X0nosugar

Odpowiedz

1

Aby ustawić wagę na dzieciach swojego Gridlayouta, użyj jednej z metod spec() (jak ta one), która przyjmuje wartość zmiennoprzecinkową.

Innym podejściem byłoby albo utworzyć niestandardowy widok (w tym przypadku trzeba ręcznie narysować elementy) lub niestandardową grupę ViewGroup (w takim przypadku niestandardowa grupa View po prostu zajmie się pozycjonowaniem elementów, to będzie być odpowiednim, jeśli planujesz mieć bardziej złożone hierarchie widoku niż zwykły TextView).

+0

Jeszcze raz dziękuję i tylko jedno pytanie: czy rozszerzam ImageButton o części do gier i chciałbym skorzystać z animacji View i ViewGroup, czy powinienem użyć GridView lub GridLayout? – 0X0nosugar

+1

@ 0X0nosugar To nie ma znaczenia. Rozszerzanie z ImageButton lub korzystanie z dowolnej grupy ViewGroup nie zmienia opcji animowania widoków bezpośrednio lub poprzez przejścia do layoutu. Powinieneś używać GridLayout tylko dlatego, że GridView jest znacznie lepiej dopasowany do innych przypadków. – Luksprog

1

-Tutaj jesteś! :>

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

Proszę wyjaśnić (edytować odpowiedź), w jaki sposób twój kod rozwiązuje problem. Z samego kodu może nie być jasne. –

+0

Testowane z trzema różnymi emulatorami (Android 5 do 7, telefon i tablet, hdpi i mdpi): to działa, więc dziękuję :) – 0X0nosugar