I have a ListActivity whose ArrayAdapter-subclass creates a (droid-fu) WebImageView. The problem is that whenever the list grows longer than can be displayed on a single page, whatever it is that calls getView() always starts from 0 and counts to 4 or 5 (depending on whether or not partial rows are visible), even when it's actually displaying an item like #12 or 14 at the top of the screen... but onClick() registers properly.
Put another way, suppose the list has 27 rows in it, and I have the app littered with Log.d statements to document everything it's doing. When the ListActivity begins, I can see it call getView with position = 0, 1, 2, 3, 4, and 5. If I touch one of the rows, onClick() fires with the correct position 0..4 (5 is offscreen) as well. So far, so good.
Now, flick the list upward by a few rows and watch the log output. Once again, getView() gets called for position=0, 1, 2, 3, 4, and 5. But if I touch one of the rows, onClick() fires for a position like 9 or 14 (which, in fact, is correct).
In other words, somewhere along the way, whatever is responsible for making the call to the ListAdapter's getView() method to render the list is forgetting about its current offset, and is always counting from 0 instead of from whatever row is, in fact, at the top of the screen.
Does anybody have any idea where to even begin looking for what might be going wrong here? Perhaps a clue about where those calls to getView() are coming from, and how the value of the position arg used for that call is determined? God forbid, is it possible to put a breakpoint at the start of getView(), then step BACKWARDS with Eclipse to see where the call to the ArrayAdapter's getView() method came from?
Update: forgot about github & managed to get a copy of my program now:
private class ChatInfoAdapter extends ArrayAdapter<ChatInfo> {
private ArrayList<ChatInfo> items;
public ChatInfoAdapter(Context context, int resourceID, ArrayList<ChatInfo> items) {
super(context, resourceID, items);
this.items = items;
// ^^^hmmm... could THIS be the problem somehow?
}
public View getView(int position, View convertView, ViewGroup parent) {
Log.d("getView", "postion=" + position);
View v = convertView;
if (v==null) {
LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.row, null);
}
ChatInfo info = items.get(position);
// ^^^ grabbing from local "items", not superclass' ArrayList. Hmmm...
if (info != null) {
TextView x = (TextView) v.findViewById(R.id.x);
TextView y = (TextView) v.findViewById(R.id.y);
//...
String url = info.getUrl();
//...
WebImageView wiv = new WebImageView(getBaseContext(), iconUrl, true, arg, arg2);
// ^^^ my slightly-hacked droid-fu WebImageView that takes some extra args
// Even if I completely screwed it up, this class should have no effect on
// the value of "position" when getView gets called at runtime, right?
// Or is there a method of ImageView that might be getting mangled somewhere
// along the line that SHOULD be reporting its position, but instead might
// be returning 0 (which might explain why position always starts from 0).
LinearLayout placeholder = (LinearLayout) v.findViewById(R.id.placeholder);
placeholder.addView(wiv);
v.setTag(info);
}
}
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Log.d("onListItemClick", "position=" + position);
//...
}
}
So... going back to the example list with ~20+ items... when it first appears, I see a flurry of activity like this in the log:
getView: position=0 getView: position=1 getView: position=2 getView: position=3 getView: position=4 getView: position=5 (possibly in a different order, or repeated a few times)
At that point, if I click on the last row, I'll see a message in the log like: onListItemClick: position=4
So far, so good. But if I scroll the list a bit, so an item ~2/3 of the way down is shown at the top of the screen, and I click the row at the bottom of the screen, I'll see a flurry of activity like THIS in the log:
getView: position=0 getView: position=1 getView: position=2 getView: position=3 getView: position=4 getView: position=5 (possibly in a different order, or repeated a few times) ... onListItemClick: position=20
In other words, it knows I clicked row 20, but the positions shown by the calls to getView never make it above position=6 or position=7, and they always begin from position=0.
(added other comments below, and made video illustrating problem)