ListView reusing views when … I don't want it

2019-01-01 11:03发布

I've got a ListView, each of item of which contains a ToggleButton. After I toggle it and then scroll up or down, the ListView is recycling the Views and so some of the others are mirroring the checked state of the ToggleButton. I don't want this. How can I prevent it?

标签: android
4条回答
不再属于我。
2楼-- · 2019-01-01 11:11

May be you should try creating your own list view with scroll view and a container that holds the children that are added to the container programatically. set the tag for identifying the child or you could use the order of the child for that

查看更多
看风景的人
3楼-- · 2019-01-01 11:12

You could use a HashMap to save your buttons state:

 private Map<Integer,Boolean> listMapBoolean = new HashMap<Integer,Boolean>();


 toggleButton.setOnCheckedChangeListener(new OnCheckedChangeListener() {
                    @Override
                    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                        if (isChecked) {
                            listMapBoolean.put(position, true);
                        } else {
                            listMapBoolean.put(position, false);
                        }
                    }
                });

and after inflating the view you read the HashMap to see if it was checked or not:

 for (Entry<Integer, Boolean> entry : listMapBoolean.entrySet()) {
                if (entry.getKey().equals(i)) {
                    if(entry.getValue()) {
                        System.out.println("ToggleButton is checked!");
                    } else {
                        System.out.println("ToggleButton is not checked!");
                    }
                }
            }

Not sure if it helps in your way. I had also problems with recycling my EditText in my ListView.

查看更多
后来的你喜欢了谁
4楼-- · 2019-01-01 11:19

Android recycles list items for performance purposes. It is highly recommended to reuse them if you want your ListView to scroll smoothly.

For each list item the getView function of your adapter is called. There, is where you have to assign the values for the item the ListView is asking for.

Have a look at this example:

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
    ViewHolder holder = null;

    if ( convertView == null )
    {
        /* There is no view at this position, we create a new one. 
           In this case by inflating an xml layout */
        convertView = mInflater.inflate(R.layout.listview_item, null);  
        holder = new ViewHolder();
        holder.toggleOk = (ToggleButton) convertView.findViewById( R.id.togOk );
        convertView.setTag (holder);
    }
    else
    {
        /* We recycle a View that already exists */
        holder = (ViewHolder) convertView.getTag ();
    }

    // Once we have a reference to the View we are returning, we set its values.

    // Here is where you should set the ToggleButton value for this item!!!

    holder.toggleOk.setChecked( mToggles.get( position ) );

    return convertView;
}

Notice that ViewHolder is a static class we use to recycle that view. Its properties are the views your list item has. It is declared in your adapter.

static class ViewHolder{
    ToggleButton toggleOk;
}

mToggles is declared as a private property in your adapter and set with a public method like this:

public void setToggleList( ArrayList<Boolean> list ){
        this.mToggles = list;
        notifyDataSetChanged();
    }

Have a look at other custom ListView examples for more information.

Hope it helps.

查看更多
大哥的爱人
5楼-- · 2019-01-01 11:25

Add this two methods to your Adapter.

@Override

public int getViewTypeCount() {                 

    return getCount();
}

@Override
public int getItemViewType(int position) {

    return position;
}
查看更多
登录 后发表回答