GridLayout (nie GridView) jak równomiernie rozciągnąć wszystkie dzieci

217

Chcę mieć siatkę 2x2 z przyciskami w środku. To tylko ICS, więc próbuję użyć nowego GridLayout.

Oto XML mojego układu:

 <?xml version="1.0" encoding="utf-8"?>
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/favorites_grid"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#00ff00"
    android:rowCount="2"
    android:columnCount="2">
  <Button
      android:text="Cell 0"
      android:layout_row="0"
      android:layout_column="0"
      android:textSize="14dip" />
  <Button
      android:text="Cell 1"
      android:layout_row="0"
      android:layout_column="1"
      android:textSize="14dip" />

  <Button
      android:text="Cell 2"
      android:layout_row="1"
      android:layout_column="0"
      android:textSize="14dip" />
  <Button
      android:text="Cell 3"
      android:layout_row="1"
      android:layout_column="1"
      android:textSize="14dip" />
</GridLayout>

Problem polega na tym, że moje poglądy nie rozciągają się równomiernie dla każdego rzędu. Powoduje to wiele dodatkowej przestrzeni po prawej stronie mojego GridLayout.

Próbowałem ustawienia, layout_gravity="fill_horizontal"ale dotyczy to tylko ostatniego widoku w wierszu. Oznacza to, że Komórka 1 rozciąga się do końca, aby zapewnić wystarczającą ilość miejsca dla Komórki 0.

Myśli, jak sobie z tym poradzić?

dnkoutso
źródło
Dlaczego nie ustawiłeś określonych rozmiarów layout_width i layout_height dla tych elementów Button?
IgorGanapolsky
Dlaczego nie użyć TableLayout w twoim przypadku?
słabypust
1
W Lollipop możemy teraz użyć android.support.v7.widget.GridLayout, liczba kolumn 3, a następnie mieć <TextView> <Space app: layout_columnWeight = "1" /> <TextView> na każdą kolumnę, aby osiągnąć pożądane efekt bez wszystkich dodatkowych kosztów, chyba że budujesz wyłącznie dla zestawu SDK 21, a następnie możesz użyć zwykłego GradLayout
AllDayAmazing

Odpowiedzi:

77

AKTUALIZACJA : Wagi są obsługiwane od API 21. Więcej informacji można znaleźć w odpowiedzi PaulT . ZAKOŃCZ AKTUALIZACJĘ Istnieją ograniczenia w korzystaniu z GridLayout. Poniższy cytat pochodzi z dokumentacji .

„GridLayout nie zapewnia wsparcia dla zasady wagi zdefiniowanej w wadze. Zasadniczo nie jest zatem możliwe skonfigurowanie GridLayout w celu rozdzielenia nadmiaru miejsca w nietrywialnych proporcjach między wiele wierszy lub kolumn ... Dla pełnej kontroli rozkład nadmiaru przestrzeni w wierszu lub kolumnie; użyj widoku podrzędnego LinearLayout, aby utrzymać komponenty w powiązanej grupie komórek. ”

Oto mały przykład, który wykorzystuje widoki podrzędne LinearLayout. (Użyłem widoków przestrzennych, które zajmują nieużywany obszar i popychają przyciski w żądane położenie.)

<GridLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:columnCount="1"
>
    <TextView
        android:text="2x2 button grid"
        android:textSize="32dip"
        android:layout_gravity="center_horizontal" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" android:orientation="horizontal">
        <Space
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_weight="1" />
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button 1" />
        <Space
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_weight="1" />
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="start"
            android:text="Button 2" />
        <Space
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_weight="1" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
    >
        <Space
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_weight="1" />
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button 3" />
        <Space
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_weight="1" />
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="start"
            android:text="Button 4" />
        <Space
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_weight="1" />
    </LinearLayout>
</GridLayout>
HenrikS
źródło
117
Ten GridLayout z kolumną 1 ma w zasadzie charakter liniowy w orientacji pionowej. To sprawia, że ​​układ jest bardziej skomplikowany. GridLayout ma uprościć i zabrać układ zagnieżdżony.
Wygraj Myo Htet
17
Właśnie znalazłem sposób! android: layout_gravity = "fill_horizontal". Jeśli korzystasz z Biblioteki wsparcia, zmień ją na grid: layout_gravity = "fill_horizontal"
zubietaroberto
6
Zgadzam się z Win Myo Htet. Wydaje się, że jest to odpowiedź na sugestie Androida, ale nie rozumiem, jak to jest poprawa w stosunku do LinearLayout. Myślałem, że powodem GridLayout było uniknięcie zagnieżdżonego LinearLayouts? Teraz nie widzę przypadku użycia GridLayout, który ma sens.
Mitch
4
Od API 21 obsługiwana jest waga
siyb
7
Wersja GridLayout w Bibliotece wsparcia obsługuje wagi i jest wstecznie kompatybilna z API 7. developer.android.com/reference/android/support/v7/widget/…
Jacob Tabak
311

Począwszy od API 21 do GridLayout dodano pojęcie masy. Aby obsługiwać starsze urządzenia z Androidem, możesz użyć GridLayout z biblioteki obsługi v7.

Poniższy plik XML podaje przykład wykorzystania ciężarów do wypełnienia szerokości ekranu.

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.GridLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:grid="http://schemas.android.com/apk/res-auto"

    android:id="@+id/choice_grid"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:padding="4dp"

    grid:alignmentMode="alignBounds"
    grid:columnCount="2"
    grid:rowOrderPreserved="false"
    grid:useDefaultMargins="true">

    <TextView
        android:layout_width="0dp"
        android:layout_height="100dp"
        grid:layout_columnWeight="1"
        grid:layout_gravity="fill_horizontal"
        android:gravity="center"
        android:background="#FF33B5E5"
        android:text="Tile1" />

    <TextView
        android:layout_width="0dp"
        android:layout_height="100dp"
        grid:layout_columnWeight="1"
        grid:layout_gravity="fill_horizontal"
        android:gravity="center"
        android:background="#FF33B5E5"
        android:text="Tile2" />

    <TextView
        android:layout_width="0dp"
        android:layout_height="100dp"
        grid:layout_columnWeight="1"
        grid:layout_gravity="fill_horizontal"
        android:gravity="center"
        android:background="#FF33B5E5"
        android:text="Tile3" />

    <TextView
        android:layout_width="0dp"
        android:layout_height="100dp"
        grid:layout_columnWeight="1"
        grid:layout_gravity="fill_horizontal"
        android:gravity="center"
        android:background="#FF33B5E5"
        android:text="Tile4" />

</android.support.v7.widget.GridLayout>
PaulT
źródło
21
Ta odpowiedź powinna być wyżej.
SD,
5
Czy można to wykorzystać do jednoczesnego wypełnienia zarówno pionowego, jak i poziomego? Chcę równomiernie rozciągniętego układu 3x3, ale próba uzyskania obu wag nie działa.
Eduardo Naveda,
Szczególnym przypadkiem kopalni było gdzie musiałem użyć FrameLayoutktóra zawierała Button and an ImageView` (w celu uzyskania ikony nałoży na przycisk, który pokazał zwrotne wizualne przy dotknięciu ... długa historia) jako część klawiatury. Ustawienie columnWeighti gravityna każdym innym Buttondziałało dobrze, ale zepsuło się FrameLayout. Pozostawiając to tylko dla FrameLayoutgotowego wszystko układa się równomiernie zgodnie z oczekiwaniami.
psyren89
1
Rozważ uwzględnienie zależności
Alwin Kesler,
1
Witaj, interesująca odpowiedź, ale jak można programowo dodać grid: layout_columnWeight = "1" dla zawyżonych dzieci?
Waza_Be
78

wprowadź opis zdjęcia tutaj

Appcompat21 GridLayout ma wagi kolumn i wierszy, których można użyć jak poniżej, aby równomiernie utworzyć każdy element siatki w gridlayout, jak na powyższym obrazku.

<android.support.v7.widget.GridLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:grid="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
grid:alignmentMode="alignBounds"
grid:columnCount="4">
<Button android:layout_width="0dp"
    style="?buttonStyle"
    android:layout_height="0dp"
    android:text="-1"
    grid:layout_columnWeight="1"
    grid:layout_rowWeight="1"
    grid:layout_gravity="fill"/>
...
...
...

onusopus
źródło
jak wyśrodkować widoki dziecka, jeśli mam tylko dwie kolumny!
Muhammad Babar
17
compile "com.android.support:gridlayout-v7:$supportVersion"
Miha_x64
W moim przypadku, po dodaniu dyrektywy kompilacji - dodatkowo musiałem podać to wywołanie „włącz” w pliku xml, aby mieć dostęp do atrybutów siatki (jak app:columnCount="2"):xmlns:app="http://schemas.android.com/apk/lib/android.support.v7.widget.GridLayout"
Gene Bo
42

Począwszy od API 21 bez biblioteki obsługi v7 z ScrollView:

wprowadź opis zdjęcia tutaj

XML:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    >

    <GridLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:columnCount="2"
            >

        <TextView
            android:layout_width="0dp"
            android:layout_height="100dp"
            android:layout_columnWeight="1"
            android:gravity="center"
            android:layout_gravity="fill_horizontal"
            android:background="@color/colorAccent"
            android:text="Tile1" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="100dp"
            android:layout_columnWeight="1"
            android:gravity="center"
            android:layout_gravity="fill_horizontal"
            android:background="@color/colorPrimaryDark"
            android:text="Tile2" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="100dp"
            android:layout_columnWeight="1"
            android:gravity="center"
            android:layout_gravity="fill_horizontal"
            android:background="@color/colorPrimary"
            android:text="Tile3" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="100dp"
            android:layout_columnWeight="1"
            android:gravity="center"
            android:layout_gravity="fill_horizontal"
            android:background="@color/colorAccent"
            android:text="Tile4" />

    </GridLayout>
</ScrollView>
t0m
źródło
Używam tego. Dziękuję Ci!
Raj Bedi
35

Możesz dynamicznie ustawić szerokość każdego dziecka:

GridLayout.LayoutParams params = (GridLayout.LayoutParams) child.getLayoutParams();
    params.width = (parent.getWidth()/parent.getColumnCount()) -params.rightMargin - params.leftMargin;
    child.setLayoutParams(params);
Rotemmiz
źródło
3
wydaje się załamać, gdy useDefaultMargins="true"- działa z nimi idealniefalse
Richard Le Mesurier
16

Spróbuj dodać następujące dane do specyfikacji GridLayout. To powinno działać.

android:useDefaultMargins="true"
Aviral
źródło
Dzięki temu mogę znów nazwać to GridLayout!
clwhisk
Powinien, ale tak naprawdę nie jest.
m0skit0
15

To jest właściwa odpowiedź

<?xml version="1.0" encoding="utf-8"?>
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/favorites_grid"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#00ff00"
    android:rowCount="2"
    android:columnCount="2">
    <Button
        android:text="Cell 0"
        android:layout_row="0"
        android:layout_column="0"
        android:layout_columnWeight="1"
        android:layout_rowWeight="1"
        android:textSize="14dip" 
        />
    <Button
        android:text="Cell 1"
        android:layout_row="0"
        android:layout_column="1"
        android:textSize="14dip"
        android:layout_columnWeight="1"
        android:layout_rowWeight="1"/>

    <Button
        android:text="Cell 2"
        android:layout_row="1"
        android:layout_column="0"
        android:textSize="14dip"
        android:layout_columnWeight="1"
        android:layout_rowWeight="1"/>
    <Button
        android:text="Cell 3"
        android:layout_row="1"
        android:layout_column="1"
        android:textSize="14dip"
        android:layout_columnWeight="1"
        android:layout_rowWeight="1"/>
</GridLayout>
the_prole
źródło
Zapraszam do komentowania tak późno, ale proszę dodać małe wyjaśnienie do swojej odpowiedzi
vatbub
1
Atrybut layout_columnWeight jest używany tylko w interfejsie API na poziomie 21 i wyższym
Vikash Parajuli
7

W końcu znalazłem rozwiązanie. Jak powiedział Rotemmiz, musisz później zrobić to dynamicznie. Ten kod rozciąga przyciski, aby wypełnić widok w poziomie, ale to samo można zrobić w pionie.

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

(20 jest dla wewnętrznego i zewnętrznego wypełnienia i marginesów. Można to zrobić bardziej uniwersalnie, ale jest to o wiele czystsze)

Następnie można go nazwać tak:

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

Należy to zrobić z obserwatorem, ponieważ musimy poczekać na narysowanie widoku, zanim wywołamy widoki.

dberm22
źródło
7

W moim przypadku przyciski dodawałem dynamicznie, więc moje rozwiązanie wymagało części XML i części Java. Musiałem znaleźć i miksować rozwiązania z kilku różnych miejsc i pomyślałem, że podzielę się nimi tutaj, aby ktoś inny, szukający podobnego rozwiązania, mógł uznać to za pomocne.

Pierwsza część mojego pliku układu XML ...

<android.support.v7.widget.GridLayout
    xmlns:grid="http://schemas.android.com/apk/res-auto"
    android:id="@+id/gl_Options"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    grid:useDefaultMargins="true">
</android.support.v7.widget.GridLayout>

grid:useDefaultMargins="true"nie jest wymagane, ale dodałem, ponieważ wyglądało to dla mnie lepiej, możesz zastosować inne efekty wizualne (np. wypełnienie), jak wspomniano w niektórych odpowiedziach tutaj. Teraz przyciski, ponieważ muszę je dodawać dynamicznie. Oto część mojego kodu Java do tworzenia tych przycisków. Podaję tylko te wiersze związane z tym kontekstem. Załóżmy, że muszę utworzyć przyciski z tylu myOptionsdostępnych dla mojego kodu i nie kopiuję również kodu 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 );
        }
    }
}

Ponieważ używamy GridLayout z biblioteki wsparcia, a nie standardowej GridLayout, musimy powiedzieć o tym ocenę w YourProject.gradepliku.

dependencies {
    compile 'com.android.support:appcompat-v7:23.4.0'
    ...
    compile 'com.android.support:gridlayout-v7:23.4.0'
}
Nashe
źródło
GridLayout.LayoutParams z GridLayout.spec (GridLayout.UNDEFINED, 1f) działały świetnie tylko wtedy, gdy grid: useDefaultMargins był fałszywy. Ponadto lParams.width = 0 wydaje się nie mieć zastosowania, ponieważ szerokość i wysokość są ustawiane przez LayoutParams.
ichalos,
4

Możesz to zrobić szybciej, zastępując metodę ViewGroup onLayout. To jest moje uniwersalne rozwiązanie:

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++;
            }
        }
    }

}

EDYCJA: Nie zapomnij match_parent dla dzieci!

android:layout_width="match_parent"
android:layout_height="match_parent"
użytkownik1557434
źródło
Może być dobrze, ale wymaga wsparcia dla dzieci i marginesów
Pascal
1
Padding dzieci jest obsługiwany, ponieważ jest ustawiony na atrybut potomny. Aby dodać obsługę marginesów, po prostu zmodyfikuj linię za pomocą funkcji „układ” w następujący sposób (gdzie zmienną marginesu jest margines w pikselach):getChildAt(i).layout(viewWidth * columnIndex + margin, viewHeight * rowIndex + margin, viewWidth * columnIndex + viewWidth - margin, viewHeight * rowIndex + viewHeight - margin);
user1557434 11.04.16
3

Najlepszym rozwiązaniem, jakie mogłem znaleźć, jest użycie układu liniowego (poziomego) dla każdego wiersza, który chcesz, i przypisanie mu szerokości przycisku (komórki) do 0dp i wagi do 1. Dla każdego układu liniowego (wierszy) przypisz wysokość do 0dp, a waga do 1. Znajdź kod poniżej - także android: layout_gravity = "center_vertical" służy do wyrównywania przycisków w rzędzie, jeśli zawierają tekst o zmiennej długości. Użycie 0dp i zważenie to całkiem fajna, ale mało znana sztuczka.

<LinearLayout
 android:id="@+id/parent_layout"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:background="@drawable/button_bue_3d"
 android:orientation="vertical" >

            <LinearLayout
                android:id="@+id/layout_row1"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1"

                android:orientation="horizontal" >

                <Button
                    android:id="@+id/button1"
                    style="?android:attr/buttonStyleSmall"
                   android:layout_height="wrap_content"
                   android:layout_width="0dp"
                   android:layout_weight="1"
                    android:clickable="false"
                   android:layout_gravity="center_vertical"
                    android:text="ssssssssssssssssssssssssss" />

                <Button
                    android:id="@+id/button2"
                    style="?android:attr/buttonStyleSmall"
                    android:clickable="false"
                    android:layout_height="wrap_content"
                     android:layout_width="0dp"
                   android:layout_weight="1"
                   android:layout_gravity="center_vertical"
                    android:text="sggggggg" />


            </LinearLayout>

            <LinearLayout
                android:id="@+id/layout_row2"
                android:layout_weight="1"
                android:layout_width="match_parent"
                  android:layout_height="0dp"

                android:orientation="horizontal" >

                <Button
                    android:id="@+id/button3"
                    style="?android:attr/buttonStyleSmall"
                    android:layout_height="wrap_content"
                     android:layout_width="0dp"
                   android:layout_weight="1"
                    android:layout_gravity="center_vertical"
                    android:text="s" />

                <Button
                    android:id="@+id/button4"
                    style="?android:attr/buttonStyleSmall"
                    android:layout_height="wrap_content"
                     android:layout_width="0dp"
                   android:layout_weight="1"
                    android:clickable="false"
                     android:layout_gravity="center_vertical"
                    android:text="s" />


            </LinearLayout>


       </LinearLayout>
jai
źródło
3

Tu masz :

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);
Nguyen Hoà
źródło
1

Chciałem mieć wyśrodkowaną tabelę z wyrównanymi do prawej etykietami i wyrównanymi do lewej wartościami. Dodatkowa przestrzeń powinna znajdować się wokół stołu. Po wielu eksperymentach i nieprzestrzeganiu tego, co dokumentacja mówi, że powinienem zrobić, wymyśliłem coś, co działa. Oto co zrobiłem:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:orientation="vertical" >

<GridLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:columnCount="2"
    android:orientation="horizontal"
    android:useDefaultMargins="true" >

    <TextView
        android:layout_gravity="right"
        android:text="Short label:" />

    <TextView
        android:id="@+id/start_time"
        android:layout_gravity="left"
        android:text="Long extended value" />

    <TextView
        android:layout_gravity="right"
        android:text="A very long extended label:" />

    <TextView
        android:id="@+id/elapsed_time"
        android:layout_gravity="left"
        android:text="Short value" />
</GridLayout>

To wydaje się działać, ale GridLayout pokazuje komunikat:

„Ten układ GridLayout lub jego element nadrzędny LinearLayout jest bezużyteczny”

Nie jestem pewien, dlaczego jest to „bezużyteczne”, gdy działa dla mnie.

Nie jestem pewien, dlaczego to działa lub czy jest to dobry pomysł, ale jeśli spróbujesz i może zaoferować lepszy pomysł, drobną poprawę lub wyjaśnienie, dlaczego to działa (lub nie działa), byłbym wdzięczny za informację zwrotną.

Dzięki.

Mitch
źródło
Wygląda to dobrze w edytorze układu, ale kończy się niepowodzeniem po uruchomieniu. :-(
Mitch
2
Komunikat „rodzic jest bezużyteczny” wynika z tego, że masz zawartość wrap_content wewnątrz wrap_content i jest to jedyny element, o ile widzę.
Ben Wilkinson
1

To dość stare pytanie, ale oczywiście interesujące dla wielu osób. W przypadku prostego układu 4 takich przycisków wydaje się, że TableLayout jest najprostszym sposobem na osiągnięcie pożądanego rezultatu.

Oto przykładowy kod pokazujący pierwsze 2 wiersze tabeli z 6 kolumnami obejmującymi szerokość jej elementu nadrzędnego. LinearLayout i ImageView w każdej komórce służą do „włączania i wyłączania” obrazu w komórce przy zachowaniu koloru komórki.

<TableLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:stretchColumns="1,2,3,4,5,6"
    android:background="@drawable/vertical_radio_button_background"
    android:padding="2dp">

    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:id="@+id/brown"
            android:tag="13"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:layout_margin="1dp"
            android:layout_column="1"
            android:background="@color/brown">

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="5dp"
                android:src="@drawable/selected_check"
                android:visibility="invisible"/>
        </LinearLayout>

        <LinearLayout
            android:id="@+id/maraschino"
            android:tag="9"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:layout_margin="1dp"
            android:layout_column="2"
            android:background="@color/maraschino">

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="5dp"
                android:src="@drawable/selected_check"
                android:visibility="invisible"/>
        </LinearLayout>

        <LinearLayout
            android:id="@+id/cayenne"
            android:tag="22"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:layout_margin="1dp"
            android:layout_column="3"
            android:background="@color/cayenne">

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="5dp"
                android:src="@drawable/selected_check"
                android:visibility="invisible"/>
        </LinearLayout>

        <LinearLayout
            android:id="@+id/maroon"
            android:tag="18"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:layout_margin="1dp"
            android:layout_column="4"
            android:background="@color/maroon">

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="5dp"
                android:src="@drawable/selected_check"
                android:visibility="invisible"/>
        </LinearLayout>

        <LinearLayout
            android:id="@+id/plum"
            android:tag="3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:layout_margin="1dp"
            android:layout_column="5"
            android:background="@color/plum">

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="5dp"
                android:src="@drawable/selected_check"
                android:visibility="invisible"/>
        </LinearLayout>

        <LinearLayout
            android:id="@+id/eggplant"
            android:tag="15"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:layout_margin="1dp"
            android:layout_column="6"
            android:background="@color/eggplant">

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="5dp"
                android:src="@drawable/selected_check"
                android:visibility="invisible"/>
        </LinearLayout>
    </TableRow>

    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:id="@+id/plum2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:layout_margin="1dp"
            android:layout_column="1"
            android:background="@color/plum">

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="5dp"
                android:src="@drawable/selected_check"
                android:visibility="invisible"/>
        </LinearLayout>

        <LinearLayout
            android:id="@+id/lavender"
            android:tag="14"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:layout_margin="1dp"
            android:layout_column="2"
            android:background="@color/lavender">

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="5dp"
                android:src="@drawable/selected_check"
                android:visibility="invisible"/>
        </LinearLayout>

        <LinearLayout
            android:id="@+id/carnation"
            android:tag="16"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:layout_margin="1dp"
            android:layout_column="3"
            android:background="@color/carnation">

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="5dp"
                android:src="@drawable/selected_check"
                android:visibility="invisible"/>
        </LinearLayout>

        <LinearLayout
            android:id="@+id/light_pink"
            android:tag="23"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:layout_margin="1dp"
            android:layout_column="4"
            android:background="@color/light_pink">

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="5dp"
                android:src="@drawable/selected_check"
                android:visibility="invisible"/>
        </LinearLayout>

        <LinearLayout
            android:id="@+id/strawberry"
            android:tag="10"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:layout_margin="1dp"
            android:layout_column="5"
            android:background="@color/strawberry">

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="5dp"
                android:src="@drawable/selected_check"
                android:visibility="invisible"/>
        </LinearLayout>

        <LinearLayout
            android:id="@+id/magenta"
            android:tag="20"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:layout_margin="1dp"
            android:layout_column="6"
            android:background="@color/magenta">

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="5dp"
                android:src="@drawable/selected_check"
                android:visibility="invisible"/>
        </LinearLayout>
    </TableRow>
</TableLayout>
hBrent
źródło
1

Chciałbym, żeby to komuś pomogło

Wynik

wprowadź opis zdjęcia tutaj

wprowadź opis zdjęcia tutaj

Kod:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:grid="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="item 0x0"
        grid:layout_column="0"
        grid:layout_columnWeight="1"
        grid:layout_gravity="center"
        grid:layout_row="0"
        grid:layout_rowWeight="1" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="item 0x1"
        grid:layout_column="1"
        grid:layout_columnWeight="1"
        grid:layout_gravity="center"
        grid:layout_row="0"
        grid:layout_rowWeight="1" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="item 0x2"
        grid:layout_column="2"
        grid:layout_columnWeight="1"
        grid:layout_gravity="center"
        grid:layout_row="0"
        grid:layout_rowWeight="1" />


    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="item 1x0"
        grid:layout_column="0"
        grid:layout_columnWeight="1"
        grid:layout_gravity="center"
        grid:layout_row="1"
        grid:layout_rowWeight="1" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="item 1x1"
        grid:layout_column="1"
        grid:layout_columnWeight="1"
        grid:layout_gravity="center"
        grid:layout_row="1"
        grid:layout_rowWeight="1" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="item 1x2"
        grid:layout_column="2"
        grid:layout_columnWeight="1"
        grid:layout_gravity="center"
        grid:layout_row="1"
        grid:layout_rowWeight="1" />


    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="item 2x0"
        grid:layout_column="0"
        grid:layout_columnWeight="1"
        grid:layout_gravity="center"
        grid:layout_row="2"
        grid:layout_rowWeight="1" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="item 2x1"
        grid:layout_column="1"
        grid:layout_columnWeight="1"
        grid:layout_gravity="center"
        grid:layout_row="2"
        grid:layout_rowWeight="1" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="item 2x2"
        grid:layout_column="2"
        grid:layout_columnWeight="1"
        grid:layout_gravity="center"
        grid:layout_row="2"
        grid:layout_rowWeight="1" />


    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="item 3x0"
        grid:layout_column="0"
        grid:layout_columnWeight="1"
        grid:layout_gravity="center"
        grid:layout_row="3"
        grid:layout_rowWeight="1" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="item 3x1"
        grid:layout_column="1"
        grid:layout_columnWeight="1"
        grid:layout_gravity="center"
        grid:layout_row="3"
        grid:layout_rowWeight="1" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="item 3x2"
        grid:layout_column="2"
        grid:layout_columnWeight="1"
        grid:layout_gravity="center"
        grid:layout_row="3"
        grid:layout_rowWeight="1" />

</android.support.v7.widget.GridLayout>
Zain
źródło
1

Wynik:

wprowadź opis zdjęcia tutaj

Wypróbuj coś takiego:

    final int MAX_COLUMN = gridView.getColumnCount(); //5
    final int MAX_ROW = gridView.getRowCount(); //7
    final int itemsCount = MAX_ROW * MAX_COLUMN; //35

    int row = 0, column = 0;

    for (int i = 0; i < itemsCount; i++) {
        ImageView view = new ImageView(this);

        //Just to provide alternate colors
        if (i % 2 == 0) {
            view.setBackgroundColor(Color.RED);
        } else {
            view.setBackgroundColor(Color.GREEN);
        }

        GridLayout.LayoutParams params = new GridLayout.LayoutParams(GridLayout.spec(row, 1F), GridLayout.spec(column, 1F));
        view.setLayoutParams(params);
        gridView.addView(view);

        column++;

        if (column >= MAX_COLUMN) {
            column = 0;
            row++;
        }
    }

Jeśli chcesz mieć określoną szerokość i wysokość dla swoich komórek, użyj:

     params.width = 100; // Your width
     params.height = 100; //your height
Eldhose M. Babu
źródło
1

To jest kod dla bardziej domyślnej aplikacji bez przycisków, jest to dla mnie bardzo przydatne

<GridLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:columnCount="1"
   >
   <TextView
       android:text="2x2 button grid"
       android:textSize="32dip"
       android:layout_gravity="center_horizontal" />

   <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:orientation="horizontal">
       <Space
           android:layout_width="wrap_content"
           android:layout_height="match_parent"
           android:layout_weight="1" />
       <TextView
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="Naam" />
       <Space
           android:layout_width="wrap_content"
           android:layout_height="match_parent"
           android:layout_weight="1" />
       <TextView
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:layout_gravity="start"
           android:text="@{viewModel.selectedItem.test2}" />
       <Space
           android:layout_width="wrap_content"
           android:layout_height="match_parent"
           android:layout_weight="1" />
   </LinearLayout>

   <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:orientation="horizontal"
       >
       <Space
           android:layout_width="wrap_content"
           android:layout_height="match_parent"
           android:layout_weight="1" />
       <TextView
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="Nummer" />
       <Space
           android:layout_width="wrap_content"
           android:layout_height="match_parent"
           android:layout_weight="1" />
       <TextView
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:layout_gravity="start"
           android:text="@{viewModel.selectedItem.test}" />
       <Space
           android:layout_width="wrap_content"
           android:layout_height="match_parent"
           android:layout_weight="1" />
   </LinearLayout>
</GridLayout>
Dh poker
źródło
1

mam ten sam problem i myślę, że po prostu ustawiam szerokość i wysokość programowo:

Ustaw szerokość przycisków za pomocą metrics.widthPixels / 2 metrics jest obiektem DisplayMetrics.

 GridLayout gridLayout=findViewById(R.id.grid);
    for (int i = 0; i <gridLayout.getChildCount() ; i++) {
        View view= gridLayout.getChildAt(i);
        if(view instanceof Button){
            Button btn = (Button) view;
            btn.setWidth(200);//metrics.widthPixels / 2
            btn.setHeight(200);//metrics.heightPixels / 7
        }
    } 
Ali Koohi
źródło
0

GridLayout

       <GridLayout
        android:layout_width="match_parent"
        android:layout_weight="3"
        android:columnCount="2"
        android:padding="10dp"
        android:rowCount="3"
        android:background="@drawable/background_down"
        android:layout_height="0dp">


        <androidx.cardview.widget.CardView
            android:layout_height="0dp"
            android:layout_width="0dp"
            android:layout_columnWeight="1"
            android:layout_rowWeight="1"
            android:layout_margin="10dp"
            android:elevation="10dp"
            app:cardCornerRadius="15dp"
            >
            <LinearLayout
                android:weightSum="3"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical"
                >

                <ImageView
                    android:layout_weight="2"
                    android:layout_width="50dp"
                    android:layout_height="50dp"
                    android:layout_margin="15dp"
                    android:src="@drawable/user" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Users"
                    android:textSize="16sp"
                    android:layout_marginStart="15dp"
                    android:layout_marginLeft="15dp" />
            </LinearLayout>

        </androidx.cardview.widget.CardView>
        <androidx.cardview.widget.CardView
            android:layout_height="0dp"
            android:layout_width="0dp"
            android:layout_columnWeight="1"
            android:layout_rowWeight="1"
            android:layout_margin="10dp"
            android:elevation="10dp"
            app:cardCornerRadius="15dp"
            >
            <LinearLayout
                android:weightSum="3"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical"
                >

                <ImageView
                    android:layout_weight="2"
                    android:layout_width="50dp"
                    android:layout_height="50dp"
                    android:layout_margin="15dp"
                    android:src="@drawable/addusers" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Add Users"
                    android:textSize="16sp"
                    android:layout_marginStart="15dp"
                    android:layout_marginLeft="15dp" />
            </LinearLayout>


        </androidx.cardview.widget.CardView>

        <androidx.cardview.widget.CardView
            android:layout_height="0dp"
            android:layout_width="0dp"
            android:layout_columnWeight="1"
            android:layout_rowWeight="1"
            android:layout_margin="10dp"
            android:elevation="10dp"
            app:cardCornerRadius="15dp"
            >
            <LinearLayout
                android:weightSum="3"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical"
                >

                <ImageView
                    android:layout_weight="2"
                    android:layout_width="50dp"
                    android:layout_height="50dp"
                    android:layout_margin="15dp"
                    android:src="@drawable/newspaper" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Report"
                    android:textSize="16sp"
                    android:layout_marginStart="15dp"
                    android:layout_marginLeft="15dp" />
            </LinearLayout>



        </androidx.cardview.widget.CardView>
        <androidx.cardview.widget.CardView
            android:layout_height="0dp"
            android:layout_width="0dp"
            android:layout_columnWeight="1"
            android:layout_rowWeight="1"
            android:layout_margin="10dp"
            android:elevation="10dp"
            app:cardCornerRadius="5dp"
            >
            <LinearLayout
                android:weightSum="3"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical"
                >

                <ImageView
                    android:layout_weight="2"
                    android:layout_width="50dp"
                    android:layout_height="50dp"
                    android:layout_margin="15dp"
                    android:src="@drawable/settings" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Settings"
                    android:textSize="16sp"
                    android:layout_marginStart="15dp"
                    android:layout_marginLeft="15dp" />
            </LinearLayout>


        </androidx.cardview.widget.CardView>

    </GridLayout>

możesz tu znaleźć wszystkie samouczki, układ siatki Android z CardView i OnItemClickListener

Richard Kamere
źródło
-2

Oto co zrobiłem i cieszę się, że to dla mnie zadziałało. Ja też chciałem siatkę przedmiotów 2x2, 3x3 itd., Która pokryłaby cały ekran. Siatki nie przylegają do szerokości ekranu. LinearLayouts to rodzaj pracy, ale nie można używać obciążników zagnieżdżonych.

Najlepszym rozwiązaniem dla mnie było używać Fragmenty użyłem tego samouczku, aby zacząć od tego, co chciałem zrobić.

Oto kod:

Główna aktywność:

public class GridHolderActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main_6);
    }
}

activity_main_6 XML (napompowuje 3 fragmenty)

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout
    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"
    android:orientation="vertical">

    <fragment
        android:id="@+id/frag1"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:name=".TwoHorizontalGridFragment"
        tools:layout="@layout/two_horiz" />
    <fragment
        android:id="@+id/frag2"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:name=".TwoHorizontalGridFragment"
        tools:layout="@layout/two_horiz" />
    <fragment
        android:id="@+id/frag3"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:name=".Grid.TwoHorizontalGridFragment"
        tools:layout="@layout/two_horiz" />

Podstawowy układ fragmentów

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="wrap_content"
    android:layout_gravity="center"
    android:layout_height="match_parent">

    <ImageQueue
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:id="@+id/img1"
        android:layout_weight="1"/>


    <ImageQueue
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:id="@+id/img2"
        android:layout_weight="1"/>
</LinearLayout>

Klasa fragmentów (obsługuje tylko inicjalizację widoku niestandardowego) napompowuje 2 płytki na 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();
}

}

Otóż ​​to!

Zasadniczo jest to dziwne obejście używania zagnieżdżonych obciążników. Daje mi idealną siatkę 2x3, która wypełnia cały ekran mojego 10-calowego tabletu i mojego HTC droid DNA. Daj mi znać, jak ci idzie!

Nlinscott
źródło
1
Jest to złe podejście, ponieważ masz wiele fragmentów, które mają całą złożoną strukturę, aby wykonać prostą taksówkę, którą można osiągnąć za pomocą gridview / gridlayout.
Raykud
OP powiedział, że potrzebuje siatki 2x2 dla kilku przycisków. Masz rację, to jest sposób na skomplikowanie. W przypadku układów zawierających więcej tekstu, widoków i innej zawartości fragmenty są najlepszym rozwiązaniem. Byłoby to również przydatne, gdyby układy były całkowicie statyczne i NIE były budowane dynamicznie.
Nlinscott,
Teraz, gdy jest więcej wsparcia dla GridLayouts w API 21, to podejście jest przesada
Nlinscott