5

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?

Lefteris
  • 14,550
  • 2
  • 56
  • 95

3 Answers3

6

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());

}
Sudar Nimalan
  • 3,962
  • 2
  • 20
  • 28
6

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);
        }
    }
}
Daniel Bo
  • 2,518
  • 1
  • 18
  • 29
1

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.