开发者

ListView and rows recycling problem

开发者 https://www.devze.com 2023-02-28 02:34 出处:网络
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.

I have this ListView:

ListView and rows recycling problem

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:

ListView and rows recycling problem

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消