Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android RelativeLayout fill_parent unexpected behavior in a ListView with varying row heights

I'm currently working on a small update to a project and I'm having an issue with Relative_Layout and fill_parent in a list view. I'm trying to insert a divider between two sections in each row, much like the divider in the call log of the default dialer. I checked out the Android source code to see how they did it, but I encountered a problem when replicating their solution.

To start, here is my row item layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:id="@+id/RelativeLayout01"
 android:layout_width="fill_parent" 
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:padding="10dip" 
 android:layout_height="fill_parent" 
 android:maxHeight="64dip" 
 android:minHeight="?android:attr/listPreferredItemHeight">
 <ImageView android:id="@+id/infoimage" 
  android:layout_width="wrap_content"
  android:layout_height="wrap_content" 
  android:clickable="true"
  android:src="@drawable/info_icon_big" 
  android:layout_alignParentRight="true" 
  android:layout_centerVertical="true"/>
 <View android:id="@+id/divider" 
  android:background="@drawable/divider_vertical_dark" 
  android:layout_marginLeft="11dip" 
  android:layout_toLeftOf="@+id/infoimage" 
  android:layout_width="1px" 
  android:layout_height="fill_parent"
  android:layout_marginTop="5dip" 
  android:layout_marginBottom="5dip" 
  android:layout_marginRight="4dip"/>
 <TextView android:id="@+id/TextView01" 
  android:textAppearance="?android:attr/textAppearanceLarge"
  android:layout_width="wrap_content" 
  android:layout_height="wrap_content"
  android:layout_centerVertical="true" 
  android:layout_toRightOf="@+id/ImageView01" 
  android:layout_toLeftOf="@+id/divider"
  android:gravity="left|center_vertical" 
  android:layout_marginLeft="4dip" 
  android:layout_marginRight="4dip"/>
 <ImageView android:id="@+id/ImageView01" 
  android:layout_width="wrap_content" 
  android:layout_height="wrap_content" 
  android:layout_alignParentLeft="true" 
  android:background="@drawable/bborder" 
  android:layout_centerVertical="true"/>
</RelativeLayout>

The issue I'm facing is that each row has a thumbnail of varying height (ImageView01). If I set the RelativeLayout's layout_height property to fill_parent, the divider does not scale vertically to fill the row (it just remains a 1px dot). If I set layout_height to "?android:attr/listPreferredItemHeight", the divider fills the row, but the thumbnails shrink. I've done some debugging in the getView() method of the adapter, and it seems that the divider's height is not being set properly once the row has its proper height.

Here is a portion of the getView() method:

public View getView(int position, View view, ViewGroup parent) {
            if (view == null) {
                view = inflater.inflate(R.layout.tag_list_item, parent, false);
            }

The rest of the method simply sets the appropriate text and images for the row.

Also, I create the inflater object in the adapter's constructor with: inflater = LayoutInflater.from(context);

Am I missing something essential? Or does fill_parent just not work with dynamic heights?

like image 841
Jameel A. Avatar asked Apr 29 '10 07:04

Jameel A.


1 Answers

If anybody else runs into this issue, the only way that I found (other than fixed height) is to switch to a LinearLayout. I'm guessing this is due to a fundamental difference in how LinearLayouts are drawn vs. RelativeLayouts. Romain Guy talks about it in this article. LinearLayouts call onMeasure() once for width and once for height, whereas RelativeLayouts do not, so they have no way of going back and filling in a vertical divider to the propper height once everything else has been laid out. The solution follows:

<LinearLayout xmlns:...
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    >
    <RelativeLayout android:id="@+id/leftContent"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        >
    </RelativeLayout>
    <View android:id="@+id/divider"
        android:layout_width="1px"
        android:layout_height="fill_parent"
        android:background="@drawable/divider" />
    <RelativeLayout android:id="@+id/rightContent"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        >
    </RelativeLayout>
</LinearLayout>

This should get you the desired result, although it's not as efficient as solely a RelativeLayout.

like image 95
Weston Avatar answered Sep 27 '22 19:09

Weston