【发布时间】:2011-08-03 03:57:58
【问题描述】:
我有一个ListView,每个item 都包含一个ToggleButton。在我切换它然后向上或向下滚动之后,ListView 正在回收视图,因此其他一些正在镜像ToggleButton 的选中状态。我不想要这个。如何预防?
【问题讨论】:
-
发布你的 getview() 方法有问题
标签: android
我有一个ListView,每个item 都包含一个ToggleButton。在我切换它然后向上或向下滚动之后,ListView 正在回收视图,因此其他一些正在镜像ToggleButton 的选中状态。我不想要这个。如何预防?
【问题讨论】:
标签: android
将这两种方法添加到您的适配器中。
@Override
public int getViewTypeCount() {
return getCount();
}
@Override
public int getItemViewType(int position) {
return position;
}
【讨论】:
.addView 将所有行都扔到那里...如果行中还有图像 - OutOfMemory 异常只是在拐角处……
Android 会出于性能目的回收列表项。如果您希望 ListView 平滑滚动,强烈建议重用它们。
对于每个列表项,调用适配器的getView 函数。在那里,您必须为 ListView 要求的项目分配值。
看看这个例子:
@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;
}
请注意,ViewHolder 是我们用来回收该视图的静态类。它的属性是您的列表项拥有的视图。它在您的适配器中声明。
static class ViewHolder{
ToggleButton toggleOk;
}
mToggles 在您的适配器中被声明为私有属性,并使用这样的公共方法进行设置:
public void setToggleList( ArrayList<Boolean> list ){
this.mToggles = list;
notifyDataSetChanged();
}
查看其他自定义 ListView 示例以了解更多信息。
希望对你有帮助。
【讨论】:
getView 时创建它(忘记 if ... else ... 语句)。不过我不推荐它。
您可以使用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);
}
}
});
膨胀视图后,您阅读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!");
}
}
}
不确定它是否对您有帮助。我在ListView 中回收我的EditText 时也遇到了问题。
【讨论】:
这会使大型列表变得如此缓慢。但是在getView()里面,你可以使用:
if (listItemView == null || ((int)listItemView.getTag()!=position)) {
listItemView = LayoutInflater.from(context).inflate(R.layout.edit_text_list_item,
parent, false);
}
listItemView.setTag(position);
// set inner Views data from ArrayList
...
标签是与View 关联的Object。并且您在回收时检查它是否可以回收。这使得每个列表项都被夸大了,没有任何东西会被回收。
这也应该防止从EditText 中删除ListView 中的文本,并且如果您的ListView 中有图像,还可以防止图像被重新排序或弄乱。
【讨论】:
也许您应该尝试使用滚动视图和一个包含以编程方式添加到容器的子项的容器创建自己的列表视图。设置用于识别孩子的标签,或者您可以使用孩子的顺序
【讨论】: