I have been reading for several hours for the solution, but I still have not found the correct answer. I have a ListFragment with a CursorAdapter. The rows are the following:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/circle"
android:src="@drawable/white_circle"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="italic"
android:textColor="#C0C0C0"
android:textSize="20sp"
android:id="@+id/tvStationName"
android:layout_toRightOf="@+id/circle"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_alignBottom="@+id/way"
android:gravity="top|start"
android:layout_marginLeft="5dp"/>
<ImageView
android:id="@+id/way"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/circle"
android:src="@drawable/white_way"/>
</RelativeLayout>
Since the ListFragment represents a route with stations (circle) and ways between the stations (way), I do not want a way to appear after the last station. Therefore, I change the image resource of the last listview element. The problem is the following:
If I scroll down the list, everything seems to be OK. Then, scrolling back to the top, at least one way is missing between the two middle stations, if it was the last element of the list. When I scroll more, I get more missing ways, and sometimes I get back some, it seems to be random.
The code of the adapter class is the following:
public class StationAdapter extends CursorAdapter {
private static final String TAG = "StationAdapter";
private Route route;
private Cursor storedCursor;
private LayoutInflater storedInflater;
private final class ViewHolder {
public TextView stationTv;
public ImageView stationIv;
public ImageView wayIv;
}
public StationAdapter(Context context, Cursor cursor, Route route) {
super(context, cursor, false);
this.route = route;
this.storedCursor = cursor;
this.storedInflater = LayoutInflater.from(context);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
final LayoutInflater inflater = LayoutInflater.from(context);
View row = inflater.inflate(R.layout.station_list_row, null);
bindView(row, context, cursor);
return row;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (storedCursor.moveToPosition(position)) {
ViewHolder holder;
if (convertView == null) {
convertView = storedInflater.inflate(R.layout.station_list_row, null);
holder = new ViewHolder();
holder.stationTv = (TextView)convertView.findViewById(R.id.tvStationName);
holder.stationIv = (ImageView)convertView.findViewById(R.id.circle);
holder.wayIv = (ImageView)convertView.findViewById(R.id.way);
convertView.setTag(holder);
}
else {
holder = (ViewHolder)convertView.getTag();
}
Station station = DbLoader.getStationByCursor(storedCursor);
// now we use the references
holder.stationTv.setText(station.getName());
if (station.equals(route.lastStation())) {
holder.wayIv.setImageResource(R.drawable.zero_way);
}
}
return convertView;
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
// UI elements
TextView stationTv = (TextView)view.findViewById(R.id.tvStationName);
ImageView wayIv = (ImageView)view.findViewById(R.id.way);
ImageView stationIv = (ImageView)view.findViewById(R.id.circle);
// station by cursor
Station station = DbLoader.getStationByCursor(cursor);
// set UI label
stationTv.setText(station.getName());
if (station.equals(route.lastStation())) {
wayIv.setImageResource(R.drawable.zero_way);
}
}
@Override
public Station getItem(int position) {
getCursor().moveToPosition(position);
return DbLoader.getStationByCursor(getCursor());
}
}
I did not want to cite too many details, I hope this will be enough.
Thanks in advance.
The issue is that the adapter tries to be more efficient. Reusing Views that you have scrolled away from.
You need to set the default position of your views, if you have a condition that changes them from their defaults.
So if you, for example, change a background image. When that view is recycled it will use the same image when it is reused.
if (station.equals(route.lastStation())) {
holder.wayIv.setImageResource(R.drawable.zero_way);
}
For example, needs to be reset to defaults.
if (station.equals(route.lastStation())) {
holder.wayIv.setImageResource(R.drawable.zero_way);
} else {
holder.wayIv.setImageResource(R.drawable.white_way);
}