172

Я хочу иметь сетку 2x2 с кнопками внутри. Это только ICS, поэтому я пытаюсь использовать новый GridLayout.GridLayout (не GridView), как растянуть всех детей равномерно

Вот XML моего макета:

<?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> 

Проблема заключается в том, что мои взгляды не растягиваться равномерно для каждой строки. Это вызывает много лишнего пространства справа от моего GridLayout.

Я пробовал установку layout_gravity="fill_horizontal", но относится только к последнему вид на ряд. Это означает, что Cell 1 растягивается полностью, чтобы дать достаточно места для ячейки 0.

Мысли о том, как это решить?

+0

Почему вы не установлены конкретные layout_width и layout_height размеры этих кнопок элементов? –

+0

Почему бы не использовать TableLayout в вашем случае? – nekavally

+0

В Lollipop теперь мы можем использовать android.support.v7.widget.GridLayout, количество столбцов 3, а затем иметь за каждый colum для достижения желаемого эффекта без всех дополнительные накладные расходы, если только вы не строите исключительно для SDK 21, а затем вы можете использовать обычный GradLayout – AllDayAmazing

ответ

65

ОБНОВЛЕНИЕ: Массы поддерживаются по API 21. См. PaulT's answer для более подробной информации. END UPDATE Существуют ограничения при использовании GridLayout, следующая цитата взята из documentation.

«GridLayout не обеспечивает поддержку принципа веса, так как , определенные в массе. В общем, это не поэтому возможно настроить GridLayout распределять лишнее пространство в нетривиальных пропорциях между несколькими рядами или столбцы ... Для полного управления с избыточным пространственным распределением в строке или столбце, используйте подкласс LinearLayout для хранения компонентов в связанной группе ячеек. "

Вот небольшой пример, который использует подходы LinearLayout. (Я использовал Space Просмотров который занимает неиспользованную область и нажимает на кнопки в нужное положение.)

<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> 
+0

. Похоже, он работает. Я пытался избежать этого, но я не вижу другого способа обойти это. Возможно, я мог бы написать свой собственный класс ViewGroup, который правильно измеряет и раскладывает своих детей. – dnkoutso

+98

Этот GridLayout с колонкой 1 в значительной степени LinearLayout в вертикальной ориентации. Это усложняет компоновку. Предполагается, что GridLayout упростит и уберет вложенный макет. –

+15

Просто нашел способ! андроид: layout_gravity = "fill_horizontal". Если вы используете библиотеку поддержки, то измените ее на сетку: layout_gravity = "fill_horizontal" – zubietaroberto

31

Вы можете установить ширину каждого ребенка динамически:

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

кажется сломанным, когда 'useDefaultMargins =" true "' - отлично работает с ними, установленным на 'false' –

+1

Может ли кто-нибудь сказать мне, где я должен добавить этот код? –

+0

Точно в onCreate у вас должен добавить этот код. –

10

Попробуйте добавить следующую строку в ваш GridLayout спецификации , Это должно сработать.

android:useDefaultMargins="true" 
+0

И с этим я могу снова называть его GridLayout! – clwhisk

+0

Должно, но на самом деле нет. – m0skit0

5

Я, наконец, нашел решение. Как сказал Ротеммиз, вы должны сделать это динамично после этого. Этот код растягивает кнопки, чтобы заполнить представление по горизонтали, но то же самое можно сделать для вертикального.

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-для внутренней и внешней прокладки и полей Это можно было бы сделать более универсально, но это намного чище.)

Тогда это можно назвать так:

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

Это должно быть сделано с наблюдателем, потому что нам нужно дождаться, пока изображение будет нарисовано, прежде чем мы назовем представления.

0

Я хотел бы иметь центрированный стол с выровненными метками и значениями, выровненными влево. Дополнительное пространство должно быть вокруг стола. После много экспериментов и не следуя за документацией, которую я должен сделать, я придумал что-то, что работает.Вот что я сделал:

<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> 

Это похоже на работу, но GridLayout показывает сообщение:

«Этот макет GridLayout или его LinearLayout родитель бесполезно»

Не знаю, почему это «бесполезно», когда оно работает для меня.

Я не уверен, почему это работает, или если это хорошая идея, но если вы попробуете его и сможете предложить лучшую идею, небольшое улучшение или объяснить, почему он работает (или не будет работать), я был бы признателен отзыв.

Спасибо.

+0

Это хорошо выглядит в редакторе макетов, но сбой при его запуске. :-( – Mitch

+1

Сообщение «parent is бесполезно», потому что у вас есть wrap_content внутри wrap_content, и это единственный элемент там, насколько я могу видеть. –

-1

Вот что я сделал, и я рад сказать, что это сработало для меня. Мне тоже нужна сетка из 2x2, 3x3 и т. Д., Чтобы покрыть весь экран. Gridlayouts не придерживаются ширины экрана. LinearLayouts вид работы, но вы не можете использовать вложенные веса.

Лучшим вариантом для меня было использование Фрагменты Я использовал this учебник, чтобы начать с того, что я хотел сделать.

Вот код:

Основная деятельность:

public class GridHolderActivity extends Activity { 

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

     setContentView(R.layout.activity_main_6); 
    } 
} 

activity_main_6 XML (надувает 3 фрагмента)

<?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" /> 

макет базы фрагмент

<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> 

Фрагмент класса (только обрабатывает инициализацию пользовательского вида) надувает 2 плитки на фрагмент

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

}

Вот это!

Это необычная работа по использованию вложенных весов. Это дает мне идеальную сетку 2x3, которая заполняет весь экран как моего 10-дюймового планшета, так и моей ДНК-дроида HTC. Дайте мне знать, как это происходит для вас!

+1

Это плохой подход, поскольку у вас есть несколько фрагментов, которые имеют – Raykud

+0

OP сказал, что им нужна сетка 2x2 для нескольких кнопок. Правильно, это способ сложный. Для макетов с большим количеством текста, просмотров и другого контента, фрагменты - это путь. Также это было бы полезно только в том случае, если макеты были полностью статичными и НЕ динамически создавались. – Nlinscott

+0

Теперь, когда в API 21 больше поддержки GridLayouts, этот подход является чрезмерным. – Nlinscott

2

Лучшее решение, которое я могу найти, - использовать линейную компоновку (по горизонтали) для каждой строки, в которой вы хотите, и внутри нее назначают ширину кнопки (ячейки) до 0dp и весу 1. Для каждого из линейных макетов (строк) присвойте высоте 0dp и весу равному 1. Найдите код ниже - android: layout_gravity = "center_vertical" используется для выравнивания кнопок в строке, если они содержат текст переменной длины. Использование 0dp и вес это довольно аккуратный, но не очень известный трюк.

<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> 
0

Это довольно старый вопрос, но, очевидно, интерес для многих людей. Для простой компоновки 4 таких кнопок кажется, что TableLayout - это самый простой способ добиться желаемого результата.

Вот пример кода, показывающего первые 2 строки таблицы с шестью столбцами, охватывающими ширину его родителя. LinearLayout и ImageView в каждой ячейке используются, чтобы позволить «включать и выключать» изображение внутри ячейки, сохраняя цвет ячейки.

<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> 
0

Старый вопрос, но хотел бы добавить свое решение. Я создал «линейную схему сетки», имитирующую сетку, но используя вложенные линейные макеты. Это позволяет растягиваться, чтобы заполнить пространство.

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

3

Вы можете сделать это гораздо быстрее с помощью переопределения метода ViewGroup OnLayout. Это мое универсальное решение:

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: Не забудьте match_parent для детей!

android:layout_width="match_parent" 
android:layout_height="match_parent" 
+0

Может быть хорошим, но нужна поддержка для заполнения и поля для детей. – Pascal

+1

Поддержка дополнений для детей, поскольку это атрибут, установленный на дочернем. Чтобы добавить поддержку маржи, просто измените строку с помощью функции «layout» следующим образом (где переменная поля - маржа в пикселях): 'getChildAt (i) .layout (viewWidth * columnIndex + margin, viewHeight * rowIndex + margin, viewWidth * columnIndex + viewWidth - margin, viewHeight * rowIndex + viewHeight - margin); ' – user1557434

247

Начиная с API 21 понятие веса было добавлено в GridLayout. Для поддержки старых Android-устройств вы можете использовать GridLayout из библиотеки поддержки v7.

В следующем XML приведен пример использования весов для заполнения ширины экрана.

<?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> 
+16

Этот ответ должен быть выше. –

+5

Может ли это использоваться для одновременного заполнения как вертикального, так и горизонтального? Я хочу равномерно растянутую компоновку 3x3, но попытка иметь оба веса не работает. – Eddnav

+0

Особый случай, когда мне приходилось использовать «FrameLayout», который содержал кнопку «Button» и «ImageView» (чтобы наложить значок на кнопку, которая отображала визуальную обратную связь при касании ... длинной истории), как часть клавиатуры. Установка 'columnWeight' и' gravity' на каждой другой кнопке' отлично работала, но ломалась на 'FrameLayout'. Оставив это только для «FrameLayout», все было равномерно распределено так, как ожидалось. – psyren89

56

enter image description here

Appcompat21 GridLayout имеет веса столбцов и строк, которые могут быть использованы, как показано ниже, чтобы равномерно создать каждый элемент сетки в GridLayout, как на изображении выше.

<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"/> 
... 
... 
... 

+0

как вы представляете интересы ребенка, если у меня есть только два столбца! –

+0

Это сработало для меня – user300375

+13

'compile" com.android.support:gridlayout-v7:$supportVersion "' –

26

Начиная с API 21 без v7 библиотеки поддержки с ScrollView:

enter image description here

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> 
6

В моем случае я добавлял кнопки динамически, моему решению потребовалась часть XML и часть Java. Я должен был найти и смешать решения из нескольких разных мест и подумал, что поделюсь им, чтобы кто-то, кто искал подобное решение, мог бы найти его полезным.

Первая часть моего файла макета 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" не требуется, но я добавил, потому что это выглядело лучше для меня, вы можете применить другие визуальные влияет (например, отступы), как указано в некоторых ответах Вот. Теперь для кнопок, поскольку я должен добавить их динамически. Вот часть Java моего кода для создания этих кнопок, я включаю только те строки, которые связаны с этим контекстом. Предположим, что мне нужно сделать кнопки из числа myOptions, доступных для моего кода, и я также не копирую код 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); 
     } 
    } 
} 

Как мы используем GridLayout из библиотеки поддержки, а не стандартной GridLayout, мы должны сказать о том, что класс в YourProject.grade файле.

dependencies { 
    compile 'com.android.support:appcompat-v7:23.4.0' 
    ... 
    compile 'com.android.support:gridlayout-v7:23.4.0' 
} 
+0

GridLayout.LayoutParams с GridLayout.spec (GridLayout.UNDEFINED, 1f) отлично справился только с сеткой: useDefaultMargins был ложным. Кроме того, lParams.width = 0 кажется, что он бесполезен, так как ширина и высота заданы LayoutParams. – ichalos

7

Это правильный ответ

<?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> 
+0

Sry для комментариев так поздно, но, пожалуйста, добавьте небольшое объяснение к вашему ответу – vatbub

0

Здесь вы:

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); 
Смежные вопросы