Hey everyone I’m not a professional coder by any stretch, but I’ve been playing around with a simple to-do list to learn the basics of android development.
I’ve been able to get just about everything I want working, but there is one problem with my listview that has me totally stumped. I’ve extended SimpleCursorAdapter in order to format the data coming from my sqlite database and change the color of the duedate text based on whether or not the duedate has expired. The formatting works flawlessly, but I’m getting some odd results with the colors.
The first few entries in the listview look as I expect them to, but as I scroll down, inconsistencies start popping up where items with no due date set will be colored red or green. The more I scroll up and down in the list, the more inconsistencies appear until eventually every row is colored whether it should be or not.
Can someone help me understand what is going on here? Please see my custom adapter below.
public class ProAdapter2 extends SimpleCursorAdapter {
private static int[] TO = {R.id.priority, R.id.projectname, R.id.duedate};
private static String[] FROM = {"priorities", "projectName", "dueDate"};
private Context context;
private int layout;
//constructor
public ProAdapter2(Context context, int layout, Cursor c) {
super(context,layout, c, FROM, TO);
this.context=context;
this.layout = layout;
}
@Override
public View newView(Context context, Cursor curso, ViewGroup parent){
Cursor c = getCursor();
final LayoutInflater inflater = LayoutInflater.from(context);
View v = inflater.inflate(layout, parent, false);
TextView txtName = (TextView) v.findViewById(R.id.projectname);
txtName.setText(c.getString(1));
TextView txtPriority = (TextView) v.findViewById(R.id.priority);
txtPriority.setText(c.getString(2));
return v;
}
@Override
public void bindView(View v, Context context, Cursor c) {
TextView txtDueDate = (TextView) v.findViewById(R.id.duedate);
TextView txtDueDateLabel = (TextView) v.findViewById(R.id.duedate_label);
TextView txtPriority = (TextView) v.findViewById(R.id.priority);
TextView txtPriorityLabel = (TextView) v.findViewById(R.id.priority_label);
TextView txtName = (TextView) v.findViewById(R.id.projectname);
LinearLayout pridate = (LinearLayout) v.findViewById(R.id.pridate);
String dueDate = c.getString(3);
String cDate = c.getString(4);
String dueDateFormated;
MyTime t = new MyTime();
Long cTimeLong = c.getLong(6);
Long dTimeLong = c.getLong(5);
dueDateFormated = t.getFormatedTime(c.getString(3));
txtDueDate.setText(dueDateFormated);
if (c.getInt(5)==0){
txtDueDate.setText("Not Set");
}
else if (cTimeLong < dTimeLong){
txtDueDate.setTextColor(Color.GREEN);
}
else if (cTimeLong > dTimeLong){
txtDueDate.setTextColor(Color.RED);
}
}
}

The simplest solution would be to add the following after
txtDueDate.setText("Not Set");:The reason is that a
ListViewrecycles theViewobjects you create in thenewViewmethod.So when
bindViewis called, thevparameter isn’t always a shiny-newViewobject, but in fact one from the top of the list that isn’t visible any more, and so previously had green or red text.So you need to make sure you explicitly set all the properties you require, including the text colour.
Aside from that, there are further optimisations you can make. For example, you shouldn’t be calling
setTextin yournewViewmethod — you should only do this in the bind method.For some good info about how the
ListViewworks, you can watch this talk or look at the PDF slides:http://www.google.com/events/io/2010/sessions/world-of-listview-android.html