Gridview height gets cut

AndroidGridview

Android Problem Overview


I'm trying to display 8 items inside a gridview. Sadly, the gridview height is always too little, so that it only shows the first row, and a little part of the second.

Setting android:layout_height="300dp" makes it work. wrap_content and fill_parent apparently not.

My grid view:

<GridView
    android:id="@+id/myId"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:horizontalSpacing="2dp"
    android:isScrollContainer="false"
    android:numColumns="4"
    android:stretchMode="columnWidth"
    android:verticalSpacing="20dp" />

My items resource:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:minHeight="?android:attr/listPreferredItemHeight" >
	
    <ImageView
        android:id="@+id/appItemIcon"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:src="@android:drawable/ic_dialog_info"
        android:scaleType="center" />      
     
	<TextView
	    android:id="@+id/appItemText"
	    android:layout_width="fill_parent"
	    android:layout_height="wrap_content"
	    android:text="My long application name"
	    android:gravity="center_horizontal"
	    android:textAppearance="?android:attr/textAppearanceSmall" />

</LinearLayout>

The issue does not seem related to a lack of vertical space.

What can I do ?

Android Solutions


Solution 1 - Android

After (too much) research, I stumbled on the excellent answer of Neil Traft.

Adapting his work for the GridView has been dead easy.

ExpandableHeightGridView.java:

package com.example;
public class ExpandableHeightGridView extends GridView
{

	boolean expanded = false;

	public ExpandableHeightGridView(Context context)
	{
		super(context);
	}

	public ExpandableHeightGridView(Context context, AttributeSet attrs)
	{
		super(context, attrs);
	}

	public ExpandableHeightGridView(Context context, AttributeSet attrs,
			int defStyle)
	{
		super(context, attrs, defStyle);
	}

	public boolean isExpanded()
	{
		return expanded;
	}

	@Override
	public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
	{
		// HACK! TAKE THAT ANDROID!
		if (isExpanded())
		{
			// Calculate entire height by providing a very large height hint.
			// View.MEASURED_SIZE_MASK represents the largest height possible.
            int expandSpec = MeasureSpec.makeMeasureSpec(MEASURED_SIZE_MASK,
                    MeasureSpec.AT_MOST);
			super.onMeasure(widthMeasureSpec, expandSpec);

			ViewGroup.LayoutParams params = getLayoutParams();
			params.height = getMeasuredHeight();
		}
		else
		{
			super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		}
	}

	public void setExpanded(boolean expanded)
	{
		this.expanded = expanded;
	}
}

Include it in your layout like this:

<com.example.ExpandableHeightGridView
    android:id="@+id/myId"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:horizontalSpacing="2dp"
    android:isScrollContainer="false"
    android:numColumns="4"
    android:stretchMode="columnWidth"
    android:verticalSpacing="20dp" />

Lastly you just need to ask it to expand:

mAppsGrid = (ExpandableHeightGridView) findViewById(R.id.myId);
mAppsGrid.setExpanded(true);

Solution 2 - Android

After using the answer from @tacone and making sure it worked, I decided to try shorting down the code. This is my result. PS: It is the equivalent of having the boolean "expanded" in tacones answer always set to true.

public class StaticGridView extends GridView {

    public StaticGridView(Context context) {
        super(context);
    }

    public StaticGridView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public StaticGridView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(MEASURED_SIZE_MASK, MeasureSpec.AT_MOST));
        getLayoutParams().height = getMeasuredHeight();
    }
}

Solution 3 - Android

Another similar approach that worked for me, is to calculate the height for one row and then with static data (you may adapt it to paginate) you can calculate how many rows you have and resize the GridView height easily.

	private void resizeGridView(GridView gridView, int items, int columns) {
	ViewGroup.LayoutParams params = gridView.getLayoutParams();
	int oneRowHeight = gridView.getHeight();
	int rows = (int) (items / columns);
	params.height = oneRowHeight * rows;
	gridView.setLayoutParams(params);
}

Use this code after setting the adapter and when the GridView is drawn or you will get height = 0.

gridView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
			@Override
			public void onGlobalLayout() {
				if (!gridViewResized) {
					gridViewResized = true;
					resizeGridView(gridView, numItems, numColumns);
				}
			}
		});

Solution 4 - Android

Found tacones answer helpfull... so i ported it to C# (Xamarin)

public class ExpandableHeightGridView: GridView
{
    bool _isExpanded = false;

    public ExpandableHeightGridView(Context context) : base(context)
    {            
    }

    public ExpandableHeightGridView(Context context, IAttributeSet attrs) : base(context, attrs)
    {            
    }

    public ExpandableHeightGridView(Context context, IAttributeSet attrs, int defStyle) : base(context, attrs, defStyle)
    {            
    }

    public bool IsExpanded
    {
        get { return _isExpanded; }

        set { _isExpanded = value;  }
    }
    
    protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        // HACK! TAKE THAT ANDROID!
        if (IsExpanded)
        {
            // Calculate entire height by providing a very large height hint.
            // View.MEASURED_SIZE_MASK represents the largest height possible.
            int expandSpec = MeasureSpec.MakeMeasureSpec( View.MeasuredSizeMask, MeasureSpecMode.AtMost);
            base.OnMeasure(widthMeasureSpec,expandSpec);                

            var layoutParameters = this.LayoutParameters;
            layoutParameters.Height = this.MeasuredHeight;
        }
        else
        {
            base.OnMeasure(widthMeasureSpec,heightMeasureSpec);    
        }
    }
}

Solution 5 - Android

Jacob R solution in Kotlin:

class ExpandableHeightGridView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : GridView(context, attrs, defStyleAttr) {

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        val expandSpec = MeasureSpec.makeMeasureSpec(MEASURED_SIZE_MASK,
            MeasureSpec.AT_MOST)
        super.onMeasure(widthMeasureSpec, expandSpec)
        layoutParams.height = measuredHeight
    }
}

After adding GridView to RecyclerView I got a full-size GridView (all rows are visible), as expected.

Solution 6 - Android

Just calculate the height for AT_MOST and set to on measure. Here GridView Scroll will not work so. Need to use Vertical Scroll View explicitly.

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
     int heightSpec;
     
     if (getLayoutParams().height == LayoutParams.WRAP_CONTENT) {
                
         heightSpec = MeasureSpec.makeMeasureSpec(
                        Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
     }
     else {
         // Any other height should be respected as is.
         heightSpec = heightMeasureSpec;
     }
     
     super.onMeasure(widthMeasureSpec, heightSpec);
 }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiontaconeView Question on Stackoverflow
Solution 1 - AndroidtaconeView Answer on Stackoverflow
Solution 2 - AndroidJacob RView Answer on Stackoverflow
Solution 3 - AndroidPelanesView Answer on Stackoverflow
Solution 4 - AndroidspaceMonsterView Answer on Stackoverflow
Solution 5 - AndroidCoolMindView Answer on Stackoverflow
Solution 6 - AndroidUday Sravan KView Answer on Stackoverflow