Search code examples
androidandroid-listviewandroid-listfragment

Custom row elements in ListFragment are displaying incorrectly after scrolling


I have a ListFragment containing a list of Earthquake objects that populates using a custom ArrayAdapter. Each element is either 'highlighted' or not, depending on whether the magnitude of the earthquake is above a certain value. The problem is that after scrolling, the 'highlighted' row colors will be applied to other rows. I suspect this is to do with the caching used in the ListView. How can I prevent this from happening?

Here is the getView method of my EarthquakeArrayAdapter class:

public View getView(int position, View convertView, ViewGroup parent) {
    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.row, parent, false);
    }

    Earthquake quake = mQuakes.get(position);
    if (quake != null) {
        TextView itemView = (TextView) convertView.findViewById(R.id.magnitude);
        if (itemView != null) {
            itemView.setText(quake.getFormattedMagnitude());
            if (quake.getRoundedMagnitude() >= mMinHighlight)
                itemView.setTextColor(Color.RED);
        }
    // Set other views in the layout, no problems here...
    }
    return convertView;
}

And here is my row.xml layout file:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >

    <TextView
       android:id="@+id/magnitude"
       style="@style/ListFont.Magnitude" />

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >
        <TextView
            android:id="@+id/date"
            style="@style/ListFont.NonMagnitude"
            android:gravity="center_horizontal|top"
            android:textSize="18sp" />
        <TextView
            android:id="@+id/location"
            style="@style/ListFont.NonMagnitude"
            android:gravity="center_horizontal|bottom"
            android:textSize="14sp" />
    </LinearLayout>

</LinearLayout>

I've watched this video on the ListView widget and I'm considering doing what Adam Powell suggests at the end - dynamically populating & expanding a LinearLayout inside a ScrollView and simply using that. My data is presently bounded between 0 and 30 items (I haven't yet tested this so don't know what the performance difference is likely to be). However, those bounds may not always stay the same - so I'd like to solve this, if I could.


Solution

  • If by highlight you mean setting the color on the magnitude TextView then you simply have to revert any changes if the magnitude isn't the required one:

    if (quake.getRoundedMagnitude() >= mMinHighlight) {
         itemView.setTextColor(Color.RED);
    } else {
         itemView.setTextColor(/*the default color*/);
    }