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

5

65

I would like to understand better how Gridview works, in particular auto_fit. Here is the XML layout:

<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/gridview"
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content"
    android:columnWidth="60dp"
    android:numColumns="auto_fit"
/>

And it works fine with a series of six thumbnails (48*48 pixels). In portrait mode, it displays one row, six columns.

with

What I don't understand is why the line android:columnWidth="60dp" is necessary, because auto_fit is expected to find the right number of columns.
Without the line android:columnWidth="60dp", it displays a grid 3 rows and 2 columns.

without

Here is the ImageAdapter class:

package com.examples.HelloGridView;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;

public class ImageAdapter extends BaseAdapter {
    private Context mContext;

    public ImageAdapter(Context c) {
        mContext = c;
    }

    public int getCount() {
        return mThumbIds.length;
    }

    public Object getItem(int position) {
        return null;
    }

    public long getItemId(int position) {
        return 0;
    }

    // create a new ImageView for each item referenced by the Adapter
    public View getView(int position, View convertView, ViewGroup parent) {
        ImageView imageView;
        if (convertView == null) {  // if it's not recycled, initialize some attributes
            imageView = new ImageView(mContext);
            imageView.setPadding(0, 0, 0, 0);
        } else {
            imageView = (ImageView) convertView;
        }

        imageView.setImageResource(mThumbIds[position]);
        return imageView;
    }

    // references to our images
    private Integer[] mThumbIds = {
            R.drawable.ic_1, R.drawable.ic_2,
            R.drawable.ic_3, R.drawable.ic_4,
            R.drawable.ic_5, R.drawable.ic_6
    };
}

Thank you for your help.

Baku answered 2/8, 2011 at 13:34 Comment(0)
C
96

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 );
Chacon answered 24/10, 2011 at 10:6 Comment(8)
It's a conceptual example of solving the problem. Since you need to know the actual width, I've included a code snipet that measures it.Chacon
@Nishant You can use setColumnWidth() right after you use setAdapter() on your GridView.Thievish
What is view in measureCellWidth( Context context, View cell)?Hissing
You wanna measure the column width by code. So cell is the view which you plan on putting in that column, so in the end the column width will be equal to cell's width.Chacon
You simply need to add gridView.setColumnWidth( width ); after you set the adapter on the gridviewOculist
@Chacon can you please help me to solve this #49958319Subdual
@Subdual this seems to be exactly the same issueChacon
I have applied lot of codes but nothing is worked for me ... can you help me in thisSubdual
J
7

According to the android:numColumns documentation

auto_fit Display as many columns as possible to fill the available space.

So if you insert ImageViews with

padding set to zero

margin set to zero

layout_width set to wrap_content

layout_height set to wrap_content

The gridView should contain the maximum possible number of children


Keep in mind Your ImageViews maybe are getting scaled (:

Jussive answered 2/8, 2011 at 14:10 Comment(3)
I have added the ImageView code. The margin is not set, I'll see if it's what I missed. Thanks.Baku
Yeah, I wouldn't necessarily believe the Android documentation. Some places still have example code which uses pre-1.0 functions!Safari
Timmmm gets it, the accepted answer shows that setting dimensions and layout options on ImageView does nothing in this case; the Gridview component is not particularly thorough with its calculations. Usually it just defaults to 2.Hetero
C
3

This may help someone... You need to find width size manually. Based on the width size you can set column

        float scalefactor = getResources().getDisplayMetrics().density * 100;
        int number = getWindowManager()
                .getDefaultDisplay().getWidth();
        int columns = (int) ((float) number / scalefactor) / 2;
        if (columns == 0 || columns == 1)
            columns = 2;
        gridView.setNumColumns(columns);
Cletacleti answered 25/3, 2015 at 6:42 Comment(0)
N
1

I find that I usually know how wide I want my columns to be. Either I know the size of my pictures or I let the user determine that size. Therefore i can just set the width in my Activity:

    gridview = (GridView) findViewById(R.id.gridview);
    SharedPreferences mySettings;
    mySettings = getSharedPreferences(Constants.PREFERENCES, Context.MODE_PRIVATE);
    int gridSize = 50 * Integer.parseInt(mySettings.getString("gridSize", "3"));
    gridview.setColumnWidth(gridSize + 10); 

Thats all . . .

Greetings from Lucerne, Stephan

Nanaam answered 31/12, 2011 at 8:50 Comment(0)
D
1

"wrap_content" works like word wrap does for text editors - if the image cannot fit into the last column size, the image flows to the next row. However, if you set the numcolumns attribute to a number then the grid may stretch/adjust the columns (stretchModde is another property that you may want to use in conjunction).

ps - although you have ticked the answer, would be glad to know if this helped.

Dispirited answered 7/5, 2013 at 3:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.