How to handle GridView with cell of different heights?

android developer picture android developer · Jan 18, 2014 · Viewed 8k times · Source

NOTE: OK, I admit the title is a bit vague, but English is not my main language, and I'm not sure how to describe the problem in one sentance.

Background

I'm trying to create an app that shows all apps information on a gridView.

The gridView has its numColumns set to auto_fit , so that its number of columns will be set nicely for all types of screens.

The problem

Since each app's information can sometimes be long, the cell height can be different from those that are next to it.

I want the grid cells to be of the same width (which works fine on all cases), and for each row, the height should be determined by the max height of the row's cells.

This causes weird things to occur:

  1. Rare: some cells are becoming empty . sometimes, when scrolling and returning there, the cells get filled...
  2. Quite common: some cells draw over other cells.
  3. Quite common: some cells don't take the space they can take , leaving empty space that cannot be clicked.
  4. Very rare: when playing with the scrolling, if you scroll all the way to the top, you get the entire grid to be empty and not scrollable ...

Here is a screenshot showing both #2 and #3 issues (they don't usually show together) :

enter image description here

Code I've used

This is the xml of the grid cell :

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/list_divider_holo_dark" >

    <ImageView
        android:id="@+id/appIconImageView"
        android:layout_width="48dip"
        android:layout_height="48dip"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:adjustViewBounds="true"
        android:contentDescription="@string/app_icon"
        android:src="@drawable/ic_menu_help" />

    <TextView
        android:id="@+id/appLabelTextView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_toLeftOf="@+id/isSystemAppImageView"
        android:layout_toRightOf="@+id/appIconImageView"
        android:ellipsize="marquee"
        android:text="label"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:textStyle="bold"
        tools:ignore="HardcodedText" />

    <TextView
        android:id="@+id/appDescriptionTextView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/appLabelTextView"
        android:layout_below="@+id/appLabelTextView"
        android:layout_toLeftOf="@+id/isSystemAppImageView"
        android:ellipsize="marquee"
        android:text="description"
        tools:ignore="HardcodedText" />

    <ImageView
        android:id="@+id/isSystemAppImageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/appDescriptionTextView"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:adjustViewBounds="true"
        android:contentDescription="@string/content_description_this_is_a_system_app"
        android:src="@drawable/stat_sys_warning" />

</RelativeLayout>

What I've tried

I've tried multiple possible solutions:

  1. using HorizontalListView seems to solve this, but then it doesn't allow clicking/long clicking on items.

  2. I've found a nice library for making the textViews have a "marquee" effect (here) , but its license isn't so permissive.

  3. Setting the cell height as fixed one or setting the textViews to have fixed lines count also work, but then it cuts down (part of) the content of the textViews without the ability to show them.

  4. I've also tried using linearLayouts instead of RelativeLayout, but it didn't help.

  5. a possible solution is to get the max height used by all views on the gridView (using getView on all items) , similar to this code, but it assumes you know the number of columns , and that you do want all cells to be of the same height.

The question

How should I handle this?

Should I really use something like StaggeredGrid ?

Is there a way to put the textViews to stay fixed in size yet allow them to show their content using scrolling (manually or automatically) ?

Answer

android developer picture android developer · Oct 20, 2015

An alternative to the above solution is to use RecyclerView and GridLayoutManager:

recyclerView.setHasFixedSize(false);
recyclerView.setLayoutManager(new GridLayoutManager(this, 2));