我有一个使用自定义游标适配器的ListActvity。在每一行我都有一个复选框。当我点击一行时,另一个活动开始。如果我单击该复选框,则必须选中该复选框,并且不必开始任何活动。
所有这一切都有效。
但是发生了以下情况:如果我选择了一些复选框,然后单击一行,等待新活动,然后单击后退按钮返回ListActivity,复选框将恢复其状态而不带任何逻辑。被检查的人现在未经检查,未经检查的人未被检查......显然是随机的。
这是我正在使用的CursorAdapter类(最后我尝试恢复正确的复选框值):
public class EmailCursorAdapter extends SimpleCursorAdapter {
Context context;
LayoutInflater inflater;
String[] from;
int[] to;
private static final String DATE_FORMAT = "dd-MM-yyyy HH:mm";
private SimpleDateFormat sdf = new SimpleDateFormat(this.DATE_FORMAT, Locale.ITALY);
public EmailCursorAdapter(Context context, int layout, Cursor c,
String[] from, int[] to) {
super(context, layout, c, from, to);
this.context=context;
this.from = from;
this.to = to;
this.inflater = LayoutInflater.from(context);
}
@Override
public View getView(int position, View v, ViewGroup parent) {
Cursor c = this.getCursor();
c.moveToPosition(position);
ViewHolder vh;
if(v == null) {
v = this.inflater.inflate(R.layout.email_adapter_row, parent, false);
vh = new ViewHolder();
v.setTag(vh);
}
else {
vh = (ViewHolder) v.getTag();
}
vh.position = position;
vh.database_id = c.getInt(c.getColumnIndex(MailDBHelper.MAIL_ID));
if (this.from.length == this.to.length) {
int i, size = this.from.length;
for (i = 0; i < size; i++) {
TextView tv = (TextView)v.findViewById(this.to[i]);
if (this.from[i].equals(MailDBHelper.MAIL_DATE)) {
Timestamp tm = new Timestamp(c.getLong(c.getColumnIndex(MailDBHelper.MAIL_DATE)));
String s = this.sdf.format(new Date(tm.getTime()));
tv.setText(s);
}
else {
tv.setText(c.getString(c.getColumnIndex(this.from[i])));
}
}
}
int unseen = c.getInt(c.getColumnIndex(MailDBHelper.MAIL_NEW));
View box = v.findViewById(R.id.email_row_box);
if (unseen == MailDBHelper.MAIL_READ) {
box.setBackgroundColor(this.context.getResources().getColor(R.color.seen_email_background));
}
else {
box.setBackgroundColor(this.context.getResources().getColor(R.color.white));
}
//////////////////////////////////////////
// HERE I TRY TO RESTORE THE RIGHT VALUE
//////////////////////////////////////////
CheckBox cb = (CheckBox) v.findViewById(R.id.email_row_check);
cb.setChecked(vh.isChecked);
Log.d("DEBUG", "checkbox at position " + position +" is " + cb.isChecked());
return v;
}
public class ViewHolder {
public int database_id;
public int position;
public boolean isChecked;
}
}
我正在使用ViewHolder
类来跟踪复选框的当前状态。这是我的活动的onListItemClick()
方法:
protected void onListItemClick (ListView l, View v, int position, long id) {
ViewHolder vh = (ViewHolder)v.getTag();
int email_id = vh.database_id;
CheckBox cb = (CheckBox) v.findViewById(R.id.email_row_check);
vh.isChecked = cb.isChecked();
if (vh.isChecked) {
Log.d("DEBUG", "checkbox at position " + vh.position + " is checked: true");
}
else {
Log.d("DEBUG", "checkbox at position " + vh.position + " is checked: false");
}
this.read_email.putExtra("email_id", email_id);
this.startActivity(this.read_email);
}
从这个方法的日志中,它似乎需要正确的位置和正确的复选框值,并将其存储在右侧ViewHolder中。
修改
根据Rashmi的回答修改了getView()
方法。
@Override
public View getView(int position, View v, ViewGroup parent) {
Cursor c = this.getCursor();
c.moveToPosition(position);
ViewHolder vh;
if(v == null) {
v = this.inflater.inflate(R.layout.email_adapter_row, parent, false);
vh = new ViewHolder();
vh.cb = (CheckBox)v.findViewById(R.id.email_row_check);
vh.cb.setOnCheckedChangeListener(ShowEmails.this);
v.setTag(vh);
}
else {
vh = (ViewHolder) v.getTag();
}
vh.position = position;
vh.database_id = c.getInt(c.getColumnIndex(MailDBHelper.MAIL_ID));
if (this.from.length == this.to.length) {
int i, size = this.from.length;
for (i = 0; i < size; i++) {
TextView tv = (TextView)v.findViewById(this.to[i]);
if (this.from[i].equals(MailDBHelper.MAIL_DATE)) {
Timestamp tm = new Timestamp(c.getLong(c.getColumnIndex(MailDBHelper.MAIL_DATE)));
String s = this.sdf.format(new Date(tm.getTime()));
tv.setText(s);
}
else {
tv.setText(c.getString(c.getColumnIndex(this.from[i])));
}
}
}
int unseen = c.getInt(c.getColumnIndex(MailDBHelper.MAIL_NEW));
View box = v.findViewById(R.id.email_row_box);
if (unseen == MailDBHelper.MAIL_READ) {
box.setBackgroundColor(this.context.getResources().getColor(R.color.seen_email_background));
}
else {
box.setBackgroundColor(this.context.getResources().getColor(R.color.white));
}
return v;
}
与复选框关联的OnCheckedChangeListener
在主要活动类中实现,它是:
@Override
public void onCheckedChanged(CompoundButton btn, boolean isChecked) {
ViewHolder vh = (ViewHolder)((View)btn.getParent()).getTag();
vh.cb.setChecked(isChecked);
}
现在,行为是不同的:只要我点击列表项,复选框就会随机重新排列,新活动开始,当我回来时,它们会回到正确的位置。这个代码是错的还是问题可能在其他地方?
答案 0 :(得分:0)
除了查看器模式之外,您还需要一些额外的东西来使复选框适配器工作。
我正在为您提供如何解决此问题的伪代码
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View view = convertView;
if (convertView == null) {
layoutInflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = layoutInflater.inflate(R.layout.cuisine_grid_item, parent,false);
holder = new ViewHolder();
holder.chkCuisine = (CheckBox) view.findViewById(R.id.chkMenu);
view.setTag(holder);
holder.chkCuisine.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton btn, boolean val) {
// TODO Auto-generated method stub
int checkedItem = (Integer) btn.getTag();
cuisineList.get(checkedItem).setChecked(val);
}
});
} else {
holder = (ViewHolder) view.getTag();
}
Cuisine cuisine = cuisineList.get(position);
holder.chkCuisine.setText(cuisine.getCuisineName());
holder.chkCuisine.setTag(position);
holder.chkCuisine.setChecked(cuisine.isChecked());
return view;
}