ListView and rows recycling problem
I have this ListView:
I'm using a custom adapter.
As you see, each row is made of a checkbox, a big TextView, and a little TextView. All items have defined the little TextView, even the "Item 2" but it's a void string.
The problem comes when I tap the EditText placed in the header of the list:
The keyboard appears, and the rows are recycled, so the getView method of my adapter is called. In that method I have an if clause where I check if the length of the "optional" text (the little TextView) is greater than 0. In that case I make some room (the space that you can see in the screenshot) and I display it.
The problem is that "Item 2" has the "optional" text initialized but it's void (0-sized). I don't understand why the if clause is executed. But more strangely... the else is also executed! In the else I just show a void string in the little TextView.
Why is this happening? The app is really simple. This is my getView method:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.list_row, null);
}
ListItem list_item = items.get(position);
TextView item_title = (TextView) convertView.findViewById(R.id.item_title);
TextView item_optional = (TextView) convertView.findViewById(R.id.item_optional);
item_title.setText(list_item.getTitle());
// If the task has an optional text, make some room and display it
if (list_item.hasOptional()) {
// This portion of code will be executed when you tap the EditText and the keyboard appears, putting the item up in the row
LayoutParams layout_params = (LayoutParams) item_title.getLayoutParams();
layout_params.topMargin = 10;
layout_params.height = -2; // -2: wrap_content
item_title.setLayoutParams(layout_params);
item_optional.setText(list_item.getOptional());
item_optional.setVisibility(0);
} else {
// This portion of code will ALSO be executed when you tap the EditText... why? this should not happen!
item_optional.s开发者_高级运维etText("");
}
return convertView;
}
The source code can be seen here (github).
When you modify a recycled view you have no idea what the state of the view is, with respect to how it might have been customized by previous calls to getView
. The view you are recycling is not a fresh-out-the-box inflation of R.layout.list_row
. Think of it as a "second hand" or "used" view.
So I can see under if (list_item.hasOptional()..
you make some modification to the item_title.getLayoutParams()
. As a view created here may later be recycled for a list item that will fail the check if (list_item.hasOptional()
under the else
code block you must reset the values you modify to the default specified in the layout.
精彩评论