Android GridLayout(不是GridView)如何均匀拉伸所有子项
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10016343/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
GridLayout (not GridView) how to stretch all children evenly
提问by dnkoutso
I want to have a 2x2 grid with a buttons inside. This is only ICS so I am trying to use the new GridLayout given.
我想要一个 2x2 网格,里面有一个按钮。这只是 ICS,所以我试图使用给定的新 GridLayout。
Here's the XML of my layout:
这是我的布局的 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>
The problem is that my views do not stretch evenly for each row. This causes a lot of extra space to the right of my GridLayout.
问题是我的视图不会为每一行均匀拉伸。这会导致我的 GridLayout 右侧有很多额外的空间。
I tried setting layout_gravity="fill_horizontal"
but that only applies to the lastview on the row. This means Cell 1 stretches all the way to give enough space for Cell 0.
我尝试设置,layout_gravity="fill_horizontal"
但这仅适用于该行的最后一个视图。这意味着单元格 1 一直延伸为单元格 0 提供足够的空间。
Thoughts on how to tackle this?
关于如何解决这个问题的想法?
采纳答案by HenrikS
UPDATE: Weights are supported as of API 21. See PaulT's answerfor more details. END UPDATEThere are limitations when using the GridLayout, the following quote is taken from the documentation.
更新:从 API 21 开始支持权重。有关更多详细信息,请参阅PaulT 的回答。 END UPDATE使用 GridLayout 时有一些限制,以下引用来自文档。
"GridLayout does not provide support for the principle of weight, as defined in weight. In general, it is not therefore possible to configure a GridLayout to distribute excess space in non-trivial proportions between multiple rows or columns ... For complete control over excess space distribution in a row or column; use a LinearLayout subview to hold the components in the associated cell group."
“GridLayout 不支持权重原则,如权重所定义。一般来说,因此不可能配置 GridLayout 以在多行或多列之间以非平凡的比例分配多余的空间......为了完全控制行或列中的多余空间分布;使用 LinearLayout 子视图将组件保存在关联的单元格组中。”
Here is a small example that uses LinearLayout subviews. (I used Space Views that takes up unused area and pushes the buttons into desired position.)
这是一个使用 LinearLayout 子视图的小例子。(我使用了占据未使用区域并将按钮推到所需位置的空间视图。)
<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>
回答by PaulT
Starting in API 21 the notion of weight was added to GridLayout. To support older android devices, you can use the GridLayout from the v7 support library.
从 API 21 开始,权重的概念被添加到 GridLayout。要支持较旧的 android 设备,您可以使用 v7 支持库中的 GridLayout。
The following XML gives an example of how you can use weights to fill the screen width.
以下 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>
回答by onusopus
Appcompat21 GridLayout has the column and row weights which can be used like below to evenly create each grid item in the gridlayout like the image above.
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"/>
...
...
...
回答by t0m
Starting in API 21 without v7 support library with ScrollView:
从 API 21 开始,没有带有 ScrollView 的 v7 支持库:
XML:
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>
回答by Rotemmiz
You can set width of every child dynamically:
您可以动态设置每个孩子的宽度:
GridLayout.LayoutParams params = (GridLayout.LayoutParams) child.getLayoutParams();
params.width = (parent.getWidth()/parent.getColumnCount()) -params.rightMargin - params.leftMargin;
child.setLayoutParams(params);
回答by Aviral
Try adding the following to your GridLayout spec. That should work.
尝试将以下内容添加到您的 GridLayout 规范中。那应该工作。
android:useDefaultMargins="true"
回答by the_prole
This is the right answer
这是正确答案
<?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>
回答by dberm22
I finally found the solution. As Rotemmiz said, you have to do it dynamically afterwards. This code stretches the buttons to fill the view horizontally, but the same can be done for vertically.
我终于找到了解决方案。正如 Rotemmiz 所说,你必须在事后动态地做。此代码拉伸按钮以水平填充视图,但垂直方向也可以这样做。
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);
}
}
(The 20 is for the internal and external padding and margins. This could be done more universally, but this is far cleaner)
(20 用于内部和外部填充和边距。这可以更普遍地完成,但这更干净)
Then it can be called like this:
那么它可以这样调用:
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);
}});
It must be done with an observer because we need to wait for the view to be drawn before we call the views.
它必须通过观察者来完成,因为我们需要在调用视图之前等待视图被绘制。
回答by Nashe
In my case I was adding the buttons dynamically so my solution required some XML part and some Java part. I had to find and mix solutions from a few different places and thought I will share it here so someone else looking for the similar solution might find it helpful.
就我而言,我是动态添加按钮的,因此我的解决方案需要一些 XML 部分和一些 Java 部分。我不得不从几个不同的地方找到并混合解决方案,并认为我会在这里分享它,这样其他寻找类似解决方案的人可能会发现它有帮助。
First part of my layout file XML...
我的布局文件 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"
is not required but I added because that looked better to me, you may apply other visual affects (e.g. padding) as mentioned in some answers here. Now for the buttons as I have to add them dynamically. Here is the Java part of my code to make these buttons, I am including only those lines related to this context. Assume I have to make buttons from as many myOptions
are available to my code and I am not copying the OnClickListener code as well.
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 );
}
}
}
As we are using GridLayout from support library and not the standard GridLayout, we have to tell grade about that in YourProject.grade
file.
由于我们使用的是支持库中的 GridLayout 而不是标准的 GridLayout,因此我们必须在YourProject.grade
文件中告知等级。
dependencies {
compile 'com.android.support:appcompat-v7:23.4.0'
...
compile 'com.android.support:gridlayout-v7:23.4.0'
}
回答by user1557434
You can make this lot faster by overriding ViewGroup onLayout method. This is my universal solution:
您可以通过覆盖 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:Don't forget match_parent for children!
编辑:不要忘记孩子的match_parent!
android:layout_width="match_parent"
android:layout_height="match_parent"