在这里找到一些答案之后,我发现自己处于一个令人不安的境地,我的Listview真的让我神经紧张。
以下是我要查找的问题:
How to save state of CheckBox while scrolling in ListView?
我使用自定义适配器和自定义行,如下所示。
我的Listview很简单,因为它显示了由三个元素组成的自定义行:
1)ImageView
显示以圆圈裁剪的联系人图片;
2)TextView
将联系人全名显示为纯文本;
3)最后是ImageView
,其中包含CheckBox
的purpouse。
请关注最后一个元素。 ImageView CheckBox将在点击时更改src
。
当用户单击时,ImageView将根据其先前的状态在检查标志和未检查的标志之间切换。可能的状态是:{checked | unchecked}
到目前为止一切顺利。
但是当我滚动ListView时,任何前面提到的更改都会在Android回收未使用的视图时消失。
这就是所谓的ViewHolder
模式。不幸的是,这种模式在两个问题上让我很烦恼:
首先,滚动时,我按字母顺序排列的列表视图变得杂乱无章。 例如不知怎的,不管怎么说,当我滚动时,第一个显示的联系人姓名会在ListView上再次显示。任何行都可能发生这种情况!因此,似乎未使用的视图被错误地重复使用。
其次,根据第一个问题,检查状态似乎确实存在,但并非总是如果它确实停留,它可能很好地保持在错误的行......这当然可以随机发生,当然。因此ViewHoder
不是一个可行的解决方案。
在取消ViewHolder模式之前,我一直使用HashMap
存储项目位置,如下所示:
ContactsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public final void onItemClick(final AdapterView<?> adapterView, final View view,
final int position, final long id) {
final ImageView check = (ImageView) view.findViewById(R.id.checkImage);
final TextView name = (TextView) view.findViewById(R.id.contactName);
final Boolean isChecked = Boolean.valueOf(checkedContactsList.isChecked(position));
if (isChecked != null && isChecked.booleanValue() == true) {
check.setImageDrawable(getActivity().getResources().getDrawable(R.drawable.unchecked_sign));
checkedContactsList.(position);
} else {
check.setImageDrawable(getActivity().getResources().getDrawable(R.drawable.checked_sign));
checkedContactsList.add(position, true);
}
}
});
我尝试添加其他值而不是position
。
我试过ContactsListView.getPositionForView(view)
我也尝试使用View的ID,但它仍然无法正常工作。
我希望我可以使用ContactsListView.getSelectedItemPosition()
但由于没有选择事件而返回-1
,因为我正在处理触摸/点击事件。
这就是我Custom Adapter
的样子:
public final View getView(final int position,
final View convertView, final ViewGroup parent) {
final LayoutInflater inflater = (LayoutInflater) this.context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View contactRowView = inflater.inflate(R.layout.contact_row, parent, false);
final ImageView contactPic = (ImageView) contactRowView.findViewById(R.id.contactPic);
final TextView contactName = (TextView) contactRowView.findViewById(R.id.contactName);
final ImageView checkImage = (ImageView) contactRowView.findViewById(R.id.checkImage);
// the list is the same as above and therefore contains the exact same entries
if (this.checkedContactsList.isChecked(position))
checkImage.setImageDrawable(this.context.getResources().getDrawable(R.drawable.checked_sign));
contactPic.setImageBitmap(cropePictureInCircle(this.contacts.get(position).getPicture()));
contactName.setText(this.contacts.get(position).getName());
return contactRowView;
}
是否有一种很好的方法可以检查选中的行,并且按照给定的字母顺序取消选中未选中的行?
谢谢!
答案 0 :(得分:1)
对于列表位置更改我知道解决方案,但对于第二个问题我仍在寻找解决方案,无论如何首先创建一个viewHolder类;
public class ViewHolder{
//put all of your textviews and image views and
//all views here like this
TextView contactName;
ImageView checkImage;
ImageView contactImage;
}
然后编辑你的适配器:
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
final View contactRowView = convertView;
ViewHolder holder;
if (contactRowView == null) {
final LayoutInflater inflater = (LayoutInflater)
this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE
);
contactRowView =
inflater.inflate(R.layout.contact_row, parent,
false);
holder = new ViewHolder():
holder.contactPic = (ImageView)
contactRowView.findViewById(R.id.contactPic);
holder.contactName = (TextView)
contactRowView.findViewById(R.id.contactName);
holder.checkImage = (ImageView)
contactRowView.findViewById(R.id.checkImage);
contactRowView.setTag(holder);
} else {
holder = contactRowView.getTag();
// the list is the same as above and therefore contains the exact same entries
if (this.checkedContactsList.isChecked(position))
holder.checkImage.setImageDrawable(this.context.get.
Resources().getDrawable(R.drawable.checked_sign));
holder.contactPic.setImageBitmap(cropePictureInCircle(this.contacts.get(position).getPicture()));
holder.contactName.setText(this.contacts.get(position).getName());
return contactRowView;
}
}
希望这有帮助和抱歉,因为从我的手机编写代码非常尴尬。