行 onClick 影响其他行
Posted
技术标签:
【中文标题】行 onClick 影响其他行【英文标题】:Row onClick affecting other rows 【发布时间】:2013-03-28 10:56:36 【问题描述】:我正在创建一个检查清单,用于标记“学生”是否存在。 我有一个 listView 成功创建了他们的详细信息,并且在右侧;一个 ImageView “X”。当您点击该行时,“X”会变成一个勾号!它成功地改变了我需要让这个程序工作的其他东西。
我的问题“是”,当我将“勾选”行之一滚动到视野之外时,它会恢复为“X”。我已经使用 View Holder 解决了这个问题。
我目前的问题是,例如,在 6 个学生的列表中。如果我“打勾”学生 1,学生 5 也将更改为打勾(尽管不在视线范围内)。如果我勾选学生 2,学生 6 将被勾选。反之亦然。我知道 onClick 代码没有针对“随机更改的行”执行,因为尽管被勾选了这些行并没有标记为“勾选”。这对我来说很奇怪,这是我的代码:
ListView listView = (ListView) findViewById(R.id.student_listview);
listView.setBackgroundColor(Color.TRANSPARENT);
listView.setCacheColorHint(Color.TRANSPARENT);
listView.setAdapter(new MySimpleArrayAdapter(this, studentIDarr));
listView.setOnItemClickListener(new OnItemClickListener()
public void onItemClick(AdapterView<?> parent, View view,
int position, long id)
ImageView img = (ImageView) view.findViewById(R.id.icon);
if(img.getTag().toString().equals("checked"))
checkListArr.set(position, "Absent");
img.setImageResource(R.drawable.remove);
img.setTag("unchecked");
else
checkListArr.set(position, "Present");
img.setImageResource(R.drawable.checked);
img.setTag("checked");
);
还有带有 ViewHolder 的适配器...
static class ViewHolder
TextView fname;
TextView sname;
TextView ID;
TextView email;
ImageView status;
public class MySimpleArrayAdapter extends ArrayAdapter<String>
private final Context context;
private final ArrayList<String> values;
public MySimpleArrayAdapter(Context context, ArrayList<String> values)
super(context, R.layout.list_class_item, values);
this.context = context;
this.values = values;
@Override
public View getView(int position, View convertView, ViewGroup parent)
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View vi = convertView;
ViewHolder holder;
if (convertView == null)
vi = inflater.inflate(R.layout.list_student_item, null);
holder = new ViewHolder();
holder.fname = (TextView) vi.findViewById(R.id.tvFname);
holder.sname = (TextView) vi.findViewById(R.id.tvSname);
holder.ID = (TextView) vi.findViewById(R.id.tvStudentID);
holder.email = (TextView) vi.findViewById(R.id.tvEmail);
holder.status= (ImageView) vi.findViewById(R.id.icon);
if(checkListArr.get(position).toString().equals("Absent"))
holder.status.setTag("unchecked");
else if (checkListArr.get(position).toString().equals("Present"))
holder.status.setTag("checked");
vi.setTag(holder);
else
holder = (ViewHolder) vi.getTag();
if(checkListArr.get(position).toString().equals("Absent"))
holder.status.setTag("unchecked");
else if (checkListArr.get(position).toString().equals("Present"))
holder.status.setTag("checked");
holder.ID.setText(values.get(position));
holder.fname.setText(fNameArray.get(position));
holder.sname.setText(sNameArray.get(position));
holder.email.setText(emailArray.get(position));
return vi;
请有人指出我的代码中的明显缺陷!感谢您的阅读!
【问题讨论】:
setOnItemClickListener(new OnItemClickListener() 注释此代码并在自定义适配器的适配器视图中添加 vi.setOnClickListener(new OnClickListener())。并将所有侦听器移动到作为列表项一部分的适配器本身. 【参考方案1】:您误解了 ListView 如何回收以前的视图。您需要将这些更改存储在底层数据模型中。
public class Model
private String fname;
private String sname;
private String email;
private boolean selected;
public Model(String fname, String sname, String email)
this.fname = fname;
selected = false;
//etc
public String getName()
return fname;
public void setName(String fname)
this.fname = fname;
public boolean isSelected()
return selected;
public void setSelected(boolean selected)
this.selected = selected;
//etc
适配器:
private final List<Model> list;
private final Activity context;
public InteractiveArrayAdapter(Activity context, List<Model> list)
super(context, R.layout.yourlayout, list);
this.context = context;
this.list = list;
static class ViewHolder
protected TextView text;
protected CheckBox checkbox;
@Override
public View getView(int position, View convertView, ViewGroup parent)
View view = null;
if (convertView == null)
LayoutInflater inflator = context.getLayoutInflater();
view = inflator.inflate(R.layout.rowbuttonlayout, null);
final ViewHolder viewHolder = new ViewHolder();
viewHolder.text = (TextView) view.findViewById(R.id.label);
viewHolder.checkbox = (CheckBox) view.findViewById(R.id.check);
viewHolder.checkbox
.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked)
Model element = (Model) viewHolder.checkbox
.getTag();
element.setSelected(buttonView.isChecked());
);
view.setTag(viewHolder);
viewHolder.checkbox.setTag(list.get(position));
else
view = convertView;
((ViewHolder) view.getTag()).checkbox.setTag(list.get(position));
ViewHolder holder = (ViewHolder) view.getTag();
holder.text.setText(list.get(position).getName());
holder.checkbox.setChecked(list.get(position).isSelected());
return view;
【讨论】:
【参考方案2】:不需要ViewHolder
。
convertView
已经是膨胀视图。当它的值为空时膨胀。然后找到您的视图并根据 new 或 convertView 中的位置设置适当的值。
使用切换<int Position, boolean Absence>
值的方法在适配器中实现SparseBooleanArray
。它是优化的 HashMap 类,用于保存和插入此类值。 AdapterView<?>
将为您提供与之交互的适配器。
ListView 还可以让您访问包含所有选定视图的类似数组以进行处理和保存。
【讨论】:
以上是关于行 onClick 影响其他行的主要内容,如果未能解决你的问题,请参考以下文章
调用函数onclick on some buttons而不影响单个onclick函数的按钮(已经为按钮分配) - JavaScript