Android: How Does Gridview Auto_Fit Find the Number of Columns

Android: How does GridView auto_fit find the number of columns?

Looking at the GridView source, it is clear that setting the padding and the height on your ImageView will not help you at all. When a column width is not specified, it just chooses a preset number of columns (2):

    private void determineColumns(int availableSpace) {

...

if (mRequestedNumColumns == AUTO_FIT) {
if (requestedColumnWidth > 0) {
// Client told us to pick the number of columns
mNumColumns = (availableSpace + requestedHorizontalSpacing) /
(requestedColumnWidth + requestedHorizontalSpacing);
} else {
// Just make up a number if we don't have enough info
mNumColumns = 2;
}
} else {
// We picked the columns
mNumColumns = mRequestedNumColumns;
}

if (mNumColumns <= 0) {
mNumColumns = 1;
}

...

The solution is to measure your column size before setting the GridView's column width. Here is a quick way to measure Views offscreen:

public int measureCellWidth( Context context, View cell )
{

// We need a fake parent
FrameLayout buffer = new FrameLayout( context );
android.widget.AbsListView.LayoutParams layoutParams = new android.widget.AbsListView.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
buffer.addView( cell, layoutParams);

cell.forceLayout();
cell.measure(1000, 1000);

int width = cell.getMeasuredWidth();

buffer.removeAllViews();

return width;
}

And then you just set the GridView's column width:

gridView.setColumnWidth( width );

Grid View auto number of columns depending on screen size

Just use different number of columns for different screen sizes - override value in different values folder (small, normal, large, xlarge), see documentation.

Example:

Activity or fragment:

<GridView
android:id="@+id/gridview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:horizontalSpacing="10dp"
android:numColumns="@integer/column_count"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:verticalSpacing="50dp"
/>

Item:

<ImageView
android:id="@+id/image"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>

values/integers.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="column_count">2</integer>
</resources>

values-large/integers.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="column_count">3</integer>
</resources>

values-xlarge/integers.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="column_count">4</integer>
</resources>

Android gridview android:numColumns=auto_fit always create only two columns

It looks like the auto-fit setting only applies if you have fixed column widths. Here is the only place in GridView source code that uses the auto-fit setting:

private boolean determineColumns(int availableSpace) {
final int requestedHorizontalSpacing = mRequestedHorizontalSpacing;
final int stretchMode = mStretchMode;
final int requestedColumnWidth = mRequestedColumnWidth;
boolean didNotInitiallyFit = false;

if (mRequestedNumColumns == AUTO_FIT) {
if (requestedColumnWidth > 0) {
// Client told us to pick the number of columns
mNumColumns = (availableSpace + requestedHorizontalSpacing) /
(requestedColumnWidth + requestedHorizontalSpacing);
} else {
// Just make up a number if we don't have enough info
mNumColumns = 2;
}
}

This private function is called during the measure / layout process. Notice that within the auto-fit if statement, unless requestedColumnWidth > 0, then you just get 2 columns, which is what you are seeing.

If a fixed width works for your app, then you need to put it in your XML like this:

<FrameLayout 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"
>
<GridView
android:id="@+id/gridView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_margin="5dp"
android:numColumns="auto_fit"
android:columnWidth="30dp"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp">
</GridView>
</FrameLayout>

How to set number of columns in GridView according to minimal and maximal column width?

In the end it was much easier than I had thought in the beginning.

Android does it more or less automatically for you, if you:

  • set android:numColumns="auto_fit" android:stretchMode="columnWidth" in the layout of the grid view and
  • set android:minWidth="200dp" in the layout of the views used for the grid view cells and
  • set android:layout_width="match_parent" android:layout_height="match_parent" in both

This means that each column must be at least 200 dp and android will determine the number of columns so that the maximal number of columns with a column width of at least 200 dp is set and if the column are wider it will stretch the cells (evenly).

I had more complicated solutions involving getViewTreeObserver().addOnGlobalLayoutListener() to wait until the grid view had determined it's size than calculating the number of columns by myself and then setting an Adapter but the solution above was identical in result and much less effort.



Related Topics



Leave a reply



Submit