Q:

Android GridView Not Scaling Properly

I have spent hours on this and looked at every related SO question I could find without a solution.
Here is my problem:
I have a gridview of images. I need 3 columns (to match the iOS version and aesthetics). If I set the numColumns to 3, I get a lot extra space between the top and bottom of the image row for each row. If I set the width to autofit, I always get 2, they look better but would prefer 3 columns.
What am I missing?
Layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="top" >

<LinearLayout 
    android:id="@+id/llayout"       
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true"
    >
    <ImageView
        android:id="@+id/header"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="#666666"
        android:clickable="false"
        android:contentDescription="@string/title_card_collection"
        android:src="@drawable/sportscard2x" />
</LinearLayout>

<GridView
    android:id="@+id/cardGrid"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_above="@+id/llayout"
    android:gravity="center"
    android:horizontalSpacing="2dip"
    android:numColumns="3"
    android:stretchMode="columnWidth"
    android:layout_alignParentBottom="true"
    android:verticalSpacing="2dip" >
</GridView>

I am hoping it is something easy that I am just missing. Thanks in advance.
UPDATED: Added Screenshot. The problem is that only 1 row is showing, if you scroll down, you see the other 3 rows, but there is a huge space in between.

A:

<edit>
Please find "Tip 3" below. Example with code can be found here.
</edit>
I think the problem is that you set the layout_height of your <GridView> to wrap_content. The grid view doesn't seem to be able to calculate it's total, wrapped height properly, hence, it's showing one row only.
You could either set the layout_height to match_parent (or any other, fixed height - like 120dp or whatever) or your could try to extend the GridView Java object and do some own calculation (you would then need to use your custom grid view object in your XML-layout as well: <com.package.to.MyCustomGridView>).
I do need to stress, though, that there aren't any well defined way of getting hold of the number of columns from the grid view in Java code prior to API 11 (you would want this in order to calculate how many rows your data adapter would produce). The getNumColumns was introduced in API 11. Neither is there a proper way of finding the spacing between rows (the getHorizontalSpacing() and getVerticalSpacing() methods were introduced in API 16).
For your reference: http://developer.android.com/reference/android/widget/GridView.html
Tip 1:
I haven't tested this my self, but you could try something like this:
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        ...
        />

    <GridView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1.0"
        ...
        />

</LinearLayout>

I.e. including your grid view in the linear layout and adding all available space to it after the image view has been laid out.
Tip 2:
You could write your own list view. There seems to be some good candy on the Sony Mobile tutorial site (and no, I'm not employed by Sony Mobile :-), nevertheless; a good tutorial is a good tutorial): http://developer.sonymobile.com/2010/05/20/android-tutorial-making-your-own-3d-list-part-1/
Tip 3:
You could extend the Java GridView object and override the onMeasure method as below example. Remember to refer to your extending GridView class in the Android layout XML file (like <com.package.MyGridView android:layout_width="match_parent" android:layout_height="wrap_content" ... />)
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int heightSpec;

    // The great Android "hackatlon" (in order to enable "wrap_content" on grid views).
    if (getLayoutParams().height == LayoutParams.WRAP_CONTENT) {
        heightSpec = MeasureSpec.makeMeasureSpec(
                Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
    }
    else {
        heightSpec = heightMeasureSpec;
    }

    super.onMeasure(widthMeasureSpec, heightSpec);
}

Hopefully you'll find some inspiration in this :-)
Cheers,
-- dbm

