[英]ListView Viewholder checkbox state
I've some problems with my ListView custom adapter (and its newly implemented viewHolder). 我的ListView自定义适配器(及其新实现的viewHolder)存在一些问题。 I have a ListView with a checkbox for each item (nothing new here).
我有一个ListView,每个项目都有一个复选框(这里没有新内容)。 The problem is, if there is more than 9 items in my list, when I check the first checkbox, the tenth will be automatically checked (same for the second with the eleventh) just like if there were one listener for both item (and I beleive it's the case in some way).
问题是,如果我的列表中有超过9个项目,当我检查第一个复选框时,将自动检查第十个(第二个与第十一个相同),就像两个项目都有一个监听器一样(和我相信它是某种情况下的情况)。
I read about the position issue with listView, view recycling and the ViewHolder way to solve it here: How can I make my ArrayAdapter follow the ViewHolder pattern? 我在这里阅读了关于listView的位置问题,查看回收和ViewHolder解决方法: 如何让我的ArrayAdapter遵循ViewHolder模式?
But I probably made something wrong because it's not working... 但我可能做错了,因为它不起作用......
public class PresenceListAdapter extends SimpleAdapter {
private LayoutInflater inflater;
private List<Integer> ids;
private List<String> statuts;
public PresenceListAdapter (Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to, List<Integer> ids, List<String> statuts)
{
super (context, data, resource, from, to);
inflater = LayoutInflater.from (context);
this.ids = ids;
this.statuts= statuts;
}
@Override
public Object getItem (int position)
{
return super.getItem (position);
}
@Override
public View getView (int position, View convertView, ViewGroup parent)
{
ViewHolder holder;
if (convertView == null)
{
convertView = inflater.inflate (R.layout.list_text_checkbox, null);
holder = new ViewHolder();
holder.btn = (Button) convertView.findViewById(R.id.btnRetard);
holder.check = (CheckBox) convertView.findViewById(R.id.checkPresent);
if (statuts.get(position).equals("P")) {
Drawable img = inflater.getContext().getResources().getDrawable(android.R.drawable.presence_online);
holder.btn.setCompoundDrawablesWithIntrinsicBounds( img, null, null, null );
holder.btn.setEnabled(true);
holder.check.setChecked(true);
}
else if(statuts.get(position).equals("R"))
{
Drawable img = inflater.getContext().getResources().getDrawable(android.R.drawable.presence_away);
holder.btn.setCompoundDrawablesWithIntrinsicBounds( img, null, null, null );
holder.btn.setEnabled(true);
holder.check.setChecked(true);
}
else
{
Drawable img = inflater.getContext().getResources().getDrawable(android.R.drawable.presence_invisible);
holder.btn.setCompoundDrawablesWithIntrinsicBounds( img, null, null, null );
holder.check.setChecked(false);
}
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
int id = ids.get(position);
if(id != 0)
{
holder.check.setTag(id);
holder.btn.setTag(id);
}
return super.getView (position, convertView, parent);
}
static class ViewHolder {
Button btn;
CheckBox check;
}
And my listener: public void changerPresent(View v) { 我的听众:public void changerPresent(View v){
CheckBox checkPresent = (CheckBox) v;
int idPersonne = (Integer) checkPresent.getTag();
View parent = (View)v.getParent();
Button btn = (Button) parent.findViewById(R.id.btnRetard);
if(checkPresent.isChecked()) {
gestion.updatePresence(idPersonne, idSeance, "P");
btn.setEnabled(true);
setBtnRetardPresent(btn);
}
else
{
gestion.updatePresence(idPersonne, idSeance, "A");
btn.setEnabled(false);
setBtnRetardAbsent(btn);
}
}
I would appreciate any help at this point, I'm working on this for hours now. 在这一点上,我将不胜感激,我现在正在努力工作几个小时。
Thank you very much. 非常感谢你。
Here's how I made it work: 这是我如何使它工作:
First, you need a separate array for your checked state. 首先,您需要一个单独的数组用于检查状态。 It has to be the same size as your adapter's
getCount()
. 它必须与适配器的
getCount()
大小相同。
Then on your getView, your checkbox's setOnCheckedChangedListener MUST PRECEED your checkbox.setChecked statements. 然后在你的getView上,你的复选框的setOnCheckedChangedListener必须打开你的checkbox.setChecked语句。
example: 例:
holder.checkBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
isChecked[position] = isChecked;
}
});
holder.checkBox.setChecked(isChecked[position]);
The problem is because of the fact that listview recycles it views 问题是因为listview回收了它的视图
so in getView(
) method 所以在
getView(
)方法中
if (convertView == null)
{
........
}
else
{
holder = (ViewHolder) convertView.getTag();
}
// Uncheck needed boxes here... You need to implement your logic
if( 'position' is checked earlier)
holder.check.setChecked(true);
else
holder.check.setChecked(false);
You need to write the code to manage the state of view if the convert is not null, because it is a already used view which may be having checked check boxes. 如果convert不为null,则需要编写代码来管理视图状态,因为它是一个已经使用过的视图,可能已经选中了复选框。
You should set CheckedBox state outside the initialization of ViewHolder, like the following code: 您应该在ViewHolder初始化之外设置CheckedBox状态,如下面的代码:
if (convertView == null) {
viewHolder = new ViewHolder();
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.checkedBox.setChecked();
BTW: use SparseBooleanArray instead of two list to store CheckedBox state. BTW:使用SparseBooleanArray而不是两个列表来存储CheckedBox状态。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.