如何在GridLayout中通过编程方式设置子元素的rowSpan或colSpan?

34

我有一个5列3行的GridLayout。现在我可以插入任意的子视图,这很棒。更好的是,我可以给某个项目分配columnSpan = 2以横跨2列(与rowSpan相同)。

问题在于,我无法在运行时编程地指定rowSpan或columnSpan。一些搜索建议使用如下代码:

layoutParams.columnSpec = GridLayout.spec(0, columnSpan);

不过我并不太理解spec参数的含义(start和size)。此时文档也相当欠缺。

非常感谢任何帮助!

6个回答

46
    GridLayout gridLayout = (GridLayout)findViewById(R.id.tableGrid);

    gridLayout.removeAllViews();

    int total = 12;
    int column = 5;
    int row = total / column;
    gridLayout.setColumnCount(column);
    gridLayout.setRowCount(row + 1);
    for(int i =0, c = 0, r = 0; i < total; i++, c++)
    {
        if(c == column)
        {
            c = 0;
            r++;
        }
        ImageView oImageView = new ImageView(this);
        oImageView.setImageResource(R.drawable.ic_launcher);
        GridLayout.LayoutParams param =new GridLayout.LayoutParams();
        param.height = LayoutParams.WRAP_CONTENT;
        param.width = LayoutParams.WRAP_CONTENT;
        param.rightMargin = 5;
        param.topMargin = 5;
        param.setGravity(Gravity.CENTER);
        param.columnSpec = GridLayout.spec(c);
        param.rowSpec = GridLayout.spec(r);
        oImageView.setLayoutParams (param);
        gridLayout.addView(oImageView);
    }

查看这张图片 - 你可以根据需要更改行数和列数


3
问题是关于通过编程方式设置跨度,但最佳答案是关于在网格布局中简单添加视图...太有趣了。 - AloDev

17

这个怎么样?

GridLayout.LayoutParams layoutParams = new GridLayout.LayoutParams();
layoutParams.rowSpec = GridLayout.spec(GridLayout.UNDEFINED, item.getRowSpan());
layoutParams.columnSpec = GridLayout.spec(GridLayout.UNDEFINED, item.getColumnSpan());

根据文档,如果您在将子视图插入GridLayout后更改列或行跨度,则还应调用 setLayoutParams。如果您在设置跨度时添加它们,则不需要这样做。


6
这是正确的答案。GridLayout.spec(start, size) 中的参数实际上分别设置了行(或列)和跨度(因此可能应该是 GridLayout.spec(rowOrColumn, span))。文档太糟糕了。 - Philip Pearl

11

您可以像这样修改GridLayout的layout_rowSpan属性:

// View allocated in first row and first column
View child = findViewById(R.id.row0column0);

GridLayout.LayoutParams params =
   new GridLayout.LayoutParams(child.getLayoutParams());

params.rowSpec = GridLayout.spec(0, 2);    // First cell in first row use rowSpan 2.
params.columnSpec = GridLayout.spec(0, 2); // First cell in first column use columnSpan 2.
child.setLayoutParams(params);

我同意文档在这方面需要稍微改进一下。


6

我正在通过程序将跨越2个单元格的列进行更改,并在此代码充气之后:

GridLayout.LayoutParams itemLP = (GridLayout.LayoutParams)gridItemV.getLayoutParams();
itemLP.columnSpec = GridLayout.spec(0, 2);
gridItemV.setLayoutParams(itemLP);

重要的是在更改列规范(columnSpec)后调用 setLayoutParams 方法。 希望对您有所帮助。

4

好的,我花了几个小时来弄清楚这里发生了什么。嗯,我没有找到任何在运行时设置 columnSpan 或 rowSpan 的有效方法。

但是我找到了一个对我有效的解决方案:

Java 代码

private LinearLayout addNewSpannedView(Integer resourceId, ViewGroup rootElement) {
    return (LinearLayout) ((ViewGroup) getLayoutInflater().inflate(resourceId, rootElement, true)).getChildAt(rootElement.getChildCount() - 1);
}
// set columnSpan depending on some logic (gridLayout is the layout to add the view's to -> in my case these are LinearLayouts)
shape = addNewSpannedView(columnSpan == 1 ? R.layout.grid_ll_col_span_1 : R.layout.grid_ll_col_span_2, gridLayout);

grid_ll_col_span_2.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="@dimen/shapeWidth"
    android:layout_height="wrap_content"
    android:layout_columnSpan="2"/>

提示:在inflate()将视图添加到根元素(即父元素)之前,非常重要的是设置宽度和高度属性

希望有人会用到这个技巧;-)


1
所以shape是一个LinearLayout?如果我想要将一个ImageButton添加到我的GridLayout中,该怎么办? - IgorGanapolsky
你好,需要同样的东西...你能再提供更多建议吗? - user4302606

0

我可能有点晚了,但是我遇到了同样的问题,为了解决它,我需要指定列的权重,然后它就完美地解决了。

这是我的代码!

val oneColSpec = GridLayout.spec(0, 2, 1f)
val twoColSpec = GridLayout.spec(2, 1, 1f)
(btnOne.layoutParams as GridLayout.LayoutParams).columnSpec = oneColSpec
(btnTwo.layoutParams as GridLayout.LayoutParams).columnSpec = twoColSpec

需要使用GridLayout的这个构造函数

public static Spec spec(int start, int size, float weight) {
    return spec(start, size, UNDEFINED_ALIGNMENT, weight);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接