当…我不希望的时候,重新使用视图

时间:2021-09-20 21:13:18

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?

我有一个ListView,每个条目都包含一个ToggleButton。在我对它进行切换,然后向上或向下滚动之后,ListView将回收视图,因此其他一些视图将镜像ToggleButton的检查状态。我不希望这样。我如何预防它?

4 个解决方案

#1


50  

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

出于性能目的,Android会回收列表项。如果您希望您的ListView平滑滚动,强烈建议重用它们。

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.

对于每个列表项,都调用适配器的getView函数。在那里,您必须为ListView要请求的项分配值。

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.

请注意,ViewHolder是我们用来循环该视图的静态类。它的属性是列表项的视图。它在您的适配器中声明。

static class ViewHolder{
    ToggleButton toggleOk;
}

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

mToggles在您的适配器中被声明为私有属性,使用如下公共方法设置:

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

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

有关更多信息,请查看其他自定义ListView示例。

Hope it helps.

希望它可以帮助。

#2


72  

Add this two methods to your Adapter.

将这两个方法添加到适配器。

@Override

public int getViewTypeCount() {                 

    return getCount();
}

@Override
public int getItemViewType(int position) {

    return position;
}

#3


3  

You could use a HashMap to save your buttons state:

您可以使用HashMap来保存按钮状态:

 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:

在放大视图之后,你会读取HashMap看看它是否被检查过:

 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.

不确定它是否对你有帮助。我在ListView中回收我的EditText也有问题。

#4


0  

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

您应该尝试使用滚动视图和一个容器来创建自己的列表视图,该容器保存按程序添加到容器中的子元素。设置标记用于标识孩子,或者您可以使用孩子的命令。

#1


50  

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

出于性能目的,Android会回收列表项。如果您希望您的ListView平滑滚动,强烈建议重用它们。

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.

对于每个列表项,都调用适配器的getView函数。在那里,您必须为ListView要请求的项分配值。

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.

请注意,ViewHolder是我们用来循环该视图的静态类。它的属性是列表项的视图。它在您的适配器中声明。

static class ViewHolder{
    ToggleButton toggleOk;
}

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

mToggles在您的适配器中被声明为私有属性,使用如下公共方法设置:

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

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

有关更多信息,请查看其他自定义ListView示例。

Hope it helps.

希望它可以帮助。

#2


72  

Add this two methods to your Adapter.

将这两个方法添加到适配器。

@Override

public int getViewTypeCount() {                 

    return getCount();
}

@Override
public int getItemViewType(int position) {

    return position;
}

#3


3  

You could use a HashMap to save your buttons state:

您可以使用HashMap来保存按钮状态:

 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:

在放大视图之后,你会读取HashMap看看它是否被检查过:

 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.

不确定它是否对你有帮助。我在ListView中回收我的EditText也有问题。

#4


0  

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

您应该尝试使用滚动视图和一个容器来创建自己的列表视图,该容器保存按程序添加到容器中的子元素。设置标记用于标识孩子,或者您可以使用孩子的命令。