Decreasing row/column count of gridlayout in android
Asked Answered
I

4

9

I need a dynamic gridlayout that can be toggled between 3 by 3 and 4 by 4. I can setRowCount and setColumnCount from 3 to 4 but not from 4 to 3. It will display following issue:

Caused by: java.lang.IllegalArgumentException: rowCount must be greater than or equal to the maximum of all grid indices (and spans) defined in the LayoutParams of each child.

Is there any work around to achieve this using gridlayout?

Illyes answered 22/10, 2014 at 18:36 Comment(0)
G
13

I realize this question is quite old, but for people who are still encountering this exception today, I'll offer an explanation that may shed some light upon how downsizing a GridLayout works and why I believe it is/was throwing an exception for the OP.

In Short:

Child views of the GridLayout can, after downsizing, occupy cells that are not within the GridLayout's grid, which is causing the IllegalArgumentException mentioned by the OP. To avoid this, remove child views that will occupy cells outside of the GridLayout's grid before actually calling setRowCount() or setColumnCount(). This can be done via GridLayout.removeView(aboutToBeIllegalChild); or by wiping the entire layout using GridLayout.removeAllViews();.

In Long:

All that calling GridLayout.setRowCount() does, is specify a new number of rows that the layout should contain. It does not, however, mess with the child views that the GridLayout currently contains, nor it's specified Spec (what column(s) and row(s) the child view occupies).

What the exception is basically telling us, and the docs confirm, is that a GridLayout does not allow any of its child views to occupy cells that are outside of the GridLayouts grid. As an example, the layout will not allow a child view to occupy cell (5, 1) when the grid is only 4 x 1.

This leads us to why the original poster was successful at dynamically increasing the GridLayout's dimensions, while being unsuccessful at decreasing it. When enlarging the dimensions, any child views that were already attached to the GridLayout with specified cells, would still be placed in legal cells if the grid received extra rows or columns dynamically. When reducing the dimensions of the grid, child views that were placed in cells that would disappear as a consequence of removing rows or columns, would now be considered illegal.

To work around this, you must either remove those (about to be) illegal child views from its parent GridLayout beforehand by calling GridLayout.removeView(aboutToBeIllegalChild); or simply wipe the entire GridLayout by calling GridLayout.removeAllViews();.

Hope this helps!

Guru answered 24/7, 2015 at 22:14 Comment(0)
P
7

Based on Teun Kooijman answer you can just change Spec in GridLayout.LayoutParams and keep all Views inside the GridLayout:

private void changeColumnCount(int columnCount) {
        if (gridLayout.getColumnCount() != columnCount) {
            final int viewsCount = gridLayout.getChildCount();
            for (int i = 0; i < viewsCount; i++) {
                View view = gridLayout.getChildAt(i);
                //new GridLayout.LayoutParams created with Spec.UNSPECIFIED
                //which are package visible
                view.setLayoutParams(new GridLayout.LayoutParams());
            }
            gridLayout.setColumnCount(columnCount);
        }
    }

You can also change Spec in other way by accessing GridLayout.LayoutParams.rowSpec and GridLayout.LayoutParams.columnSpec

Pursy answered 1/6, 2016 at 11:42 Comment(5)
UpVote: The key point here is to replace the child's LayoutParams but I had to copy the width and height values from the old LPs to the new LPs.Grounds
Hi, great, I have modified your answer to show how to copy the previous parameters to new one. Here: #26515173Circumvolution
Not a perfect answer, but still upvoted, because your solution work, need just some small modification to make it perfect.Grecoroman
@Grecoroman would've been better if you said what is the problemInsolvent
I created a menu using that, and after some time on clicking and returning to the menu, the menu glitch like crazy...Grecoroman
S
1

For me, the issue was to change the number of columns of the GridView when the app changes the orientation. I achieved it by putting the bellow code in public void onConfigurationChanged(Configuration newConfig).

if (mGridLayout.getColumnCount() != getResources().getInteger(R.integer.nav_columns)) {
        final int viewsCount = mGridLayout.getChildCount();
        for (int i = 0; i < viewsCount; i++) {
            View view = mGridLayout.getChildAt(i);
            GridLayout.LayoutParams layoutParams = new GridLayout.LayoutParams();
            int colIndex = i%getResources().getInteger(R.integer.nav_columns);
            int rowIndex = i/getResources().getInteger(R.integer.nav_columns);
            layoutParams.height = LinearLayout.LayoutParams.WRAP_CONTENT;
            layoutParams.width = 0;
            layoutParams.columnSpec = GridLayout.spec(colIndex,1,GridLayout.FILL,1f);
            layoutParams.rowSpec = GridLayout.spec(rowIndex);
            view.setLayoutParams(layoutParams);
        }
        mGridLayout.setColumnCount(getResources().getInteger(R.integer.nav_columns));
    }

The layout parameter values may need change depending on your need.

Serieswound answered 20/2, 2017 at 9:12 Comment(0)
C
0

According to @Hensin 's answer, I have modify his codes for show how to copy the previous grid items layout parameters as following:

if (gridLayout.getColumnCount() != columnCount) {
    final int viewsCount = gridLayout.getChildCount();
    for (int i = 0; i < viewsCount; i++) {
        View view = gridLayout.getChildAt(i);

        GridLayout.LayoutParams oldParams = (GridLayout.LayoutParams) view.getLayoutParams();
        GridLayout.LayoutParams newParams = new GridLayout.LayoutParams();
        newParams.width = oldParams.width;
        newParams.height = oldParams.height;
        newParams.setMargins(oldParams.leftMargin, oldParams.topMargin, oldParams.rightMargin, oldParams.bottomMargin);
                    
        view.setLayoutParams(newParams);
    }
    gridLayout.setColumnCount(columnCount);
}

You can now re order your items with almost the same layout parameters

Circumvolution answered 20/6, 2022 at 22:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.