Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get GridView actual column width in Android

Hello fellow developers.

I have a Grid View in an android application. The grid view has the setting to automatically fit the number of columns and has a minimum column width of 250 pixels.

Inside the grid cells, I have a LinearLayout that has an Image View and some Text Views.

I want my Image View to be always square, but unfortunately I was not able to do this with any layout settings (open to suggestions here, if there is an option I missed).

So my idea is that I should somehow get the grid column width in my image Loading class and adjust the imageView height dynamically there, to match the width.

I failed getting the column width though. If I set a breakPoint in my public View getView(int position, View convertView, ViewGroup parent) I see that my parent ViewGroup is the Grid and it has the correct value of the column width, but when I use:

GridView mGridView = (GridView)parent;
int width = mGridView.getColumnWidth();

the app crashes as it says there is no getColumnWidth method.

Any help here?

like image 492
Lefteris Avatar asked Jan 06 '13 22:01

Lefteris


3 Answers

The solution may be extending your ImageView and overriding onMesure() method according to your requirement:

onMeasure(int widthMeasureSpec, int heightMeasureSpec){
   super.onMeasure(widthMeasureSpec,heightMeasureSpec);
   setMeasuredDimension(getMeasuredWidth(),getMeasuredWidth());

}
like image 106
Sudar Nimalan Avatar answered Nov 19 '22 15:11

Sudar Nimalan


Just in case someone is looking for a way to get the actual columnWidth pre api 16(as was i when i saw this post), this is how i retrieve it.

I extended the GridView and overrode the getColumnWidth Method with this one

@SuppressLint("NewApi")
@Override
public int getColumnWidth() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
        return super.getColumnWidth();
    else {
        try {
            Field field = GridView.class.getDeclaredField("mColumnWidth");
            field.setAccessible(true);
            Integer value = (Integer) field.get(this);
            field.setAccessible(false);

            return value.intValue();
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
}
like image 6
Daniel Bo Avatar answered Nov 19 '22 16:11

Daniel Bo


An alternative to Daniel Bo's answer is to manually calculate the value:

private int getColumnWidth(Context context, GridView gridView) {
    if (android.os.Build.VERSION.SDK_INT >= 16)
        return gridView.getColumnWidth();

    Resources res = context.getResources();
    int lPad = (int)res.getDimension(R.dimen.left_padding);
    int rPad = (int)res.getDimension(R.dimen.right_padding);
    int hSpace = (int)res.getDimension(R.dimen.horizontal_spacing);
    int cols = gridView.getNumColumns();
    int width = gridView.getWidth();

    return (width - lPad - rPad + hSpace) / cols - hSpace;
}

Notice that this only works for API higher than 11 (Honeycomb) and assumes you set up the GridView with some values defined as resources. Consider for example that you have a dimens.xml that has:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <dimen name="left_padding">4dp</dimen>
    <dimen name="right_padding">8dp</dimen>
    <dimen name="horizontal_spacing">2dp</dimen>
</resources>

And then your layout XML file has:

<GridView
    ...
    android:horizontalSpacing="@dimen/horizontal_spacing"
    android:paddingLeft="@dimen/left_padding"
    android:paddingRight="@dimen/right_padding"
    ...
    />

And if you have many similar GridViews, it might be a good idea to put these properties in a custom style.

At least this worked for me without having to use reflection. Note that it would probably be overkill to call this function frequently.

Hope this helps someone.

like image 1
Janito Vaqueiro Ferreira Filho Avatar answered Nov 19 '22 16:11

Janito Vaqueiro Ferreira Filho