我正在使用ListView,它使用自定义ResourceCursorAdapter来显示TextView和CheckBox。 TextView和CheckBox从Cursor获取它们的状态。我一直遇到一些问题,最近的一次是当我滚动一些行时,文本来自旧的TextViews,并且当它们不应该被选中时会选择一些CheckBoxes。我添加了一个日志行来查看发生了什么,这让我更加困惑。
@Override
public void bindView(View v, Context ctx, Cursor c) {
ViewHolder holder = (ViewHolder)v.getTag();
holder.tv.setText(holder.tvText);
holder.cb.setChecked(holder.checked);
Log.d(TAG, "in bindView, rowId:" + holder.rowId + " Scripture:" + holder.tvText);
}
@Override
public View newView(Context ctx, Cursor c, ViewGroup vg){
View v = li.inflate(layout, vg, false);
ViewHolder holder;
holder = new ViewHolder();
holder.tv = (TextView)v.findViewById(to[0]);
holder.tvText = c.getString(c.getColumnIndex(from[0]));
holder.cb = (CheckBox)v.findViewById(to[1]);
holder.rowId = c.getLong(c.getColumnIndex(from[2]));
holder.checked = (c.getString(c.getColumnIndexOrThrow(from[1])).equals("n")) ?
false : true;
holder.cb.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
View rowView = ((View)v.getParent());
ViewHolder holder = (ViewHolder)rowView.getTag();
holder.checked = (holder.checked == false) ? true : false;
smDb.setMemorized(holder.rowId);
rowView.setTag(holder);
Log.d(TAG, "check box clicked: " + holder.rowId);
}});
Log.d(TAG, "in newView, rowId:" + holder.rowId);
v.setTag(holder);
return v;
}
static class ViewHolder {
TextView tv;
String tvText;
CheckBox cb;
boolean checked;
Long rowId;
}
日志输出
in newView, rowId:26
in bindView, rowId:26 Scripture:Matthew 5:14-6
in bindView, rowId:26 Scripture:Matthew 5:14-6
in bindView, rowId:26 Scripture:Matthew 5:14-6
in bindView, rowId:26 Scripture:Matthew 5:14-6
in bindView, rowId:26 Scripture:Matthew 5:14-6
in bindView, rowId:26 Scripture:Matthew 5:14-6
in bindView, rowId:26 Scripture:Matthew 5:14-6
in bindView, rowId:26 Scripture:Matthew 5:14-6
in bindView, rowId:26 Scripture:Matthew 5:14-6
in bindView, rowId:26 Scripture:Matthew 5:14-6
in bindView, rowId:26 Scripture:Matthew 5:14-6
in newView, rowId:27
in bindView, rowId:27 Scripture:Matthew 6:24
in newView, rowId:28
in bindView, rowId:28 Scripture:Matthew 16:15-9
in newView, rowId:29
in bindView, rowId:29 Scripture:Matthew 25:40
in newView, rowId:30
in bindView, rowId:30 Scripture:Luke 24:36-9
in newView, rowId:31
in bindView, rowId:31 Scripture:John 3:5
in newView, rowId:32
in bindView, rowId:32 Scripture:John 7:17
in newView, rowId:33
in bindView, rowId:33 Scripture:John 10:16
in newView, rowId:34
in bindView, rowId:34 Scripture:John 14:15
in newView, rowId:26
in bindView, rowId:26 Scripture:Matthew 5:14-6
in bindView, rowId:26 Scripture:Matthew 5:14-6
in bindView, rowId:26 Scripture:Matthew 5:14-6
in bindView, rowId:26 Scripture:Matthew 5:14-6
in bindView, rowId:26 Scripture:Matthew 5:14-6
in bindView, rowId:26 Scripture:Matthew 5:14-6
in bindView, rowId:26 Scripture:Matthew 5:14-6
in bindView, rowId:26 Scripture:Matthew 5:14-6
in bindView, rowId:26 Scripture:Matthew 5:14-6
in bindView, rowId:26 Scripture:Matthew 5:14-6
答案 0 :(得分:1)
这是导致您的问题的回收视图。
我不确定这是处理它的最流畅的方式,但这就是我做到的。我创建了一个数组来保存我的按钮状态信息,然后在我的getView方法中使用它来确保即使元素离开屏幕也能保持状态。
我的一个项目中的示例,其中我有一个列表适配器,每行上的按钮可以有多个状态(文本和颜色):
public class ButtonCursorAdapter extends SimpleCursorAdapter {
private Cursor c; // Passed in cursor
private Context context;
private Activity activity;
public static String[] atdState; // String array to hold button state
public static String[] atdRow; // Matching string array to hold db rowId
public ButtonCursorAdapter(Context context, int layout, Cursor c,
String[] from, int[] to) {
super(context, layout, c, from, to);
this.c = c;
this.context = context;
this.activity = (Activity) context;
atdState = new String[c.getCount()]; // initialize button state array
atdRow = new String[c.getCount()]; // initialize db rowId array
c.moveToFirst();
int i = 0;
while (c.isAfterLast() == false) {
if (c.getString(3) == null) { // if state is null, set to " "
atdState[i] = " ";
} else {
atdState[i] = c.getString(3); // set state to state saved in db
}
atdRow[i] = c.getString(0); // set the rowId from the db
i++;
c.moveToNext();
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null)
convertView = View.inflate(context,
R.layout.listlayoutdoublebutton, null);
final int pos = position;
View row = convertView;
c.moveToPosition(position);
TextView first = (TextView) convertView.findViewById(R.id.ListItem1);
TextView last = (TextView) convertView.findViewById(R.id.ListItem2);
Button atdButton = (Button) convertView.findViewById(R.id.attendbutton);
first.setText(c.getString(1));
last.setText(c.getString(2));
atdButton.setText(atdState[position]); // set the button state
if (atdState[position].equals("P")) { // colorize the button depending on state
atdButton.getBackground().setColorFilter(0xFF00FF00,
PorterDuff.Mode.MULTIPLY);
} else if (atdState[position].equals("T")) {
atdButton.getBackground().setColorFilter(0xFFFFFF00,
PorterDuff.Mode.MULTIPLY);
} else if (atdState[position].equals("E")) {
atdButton.getBackground().setColorFilter(0xFFFF6600,
PorterDuff.Mode.MULTIPLY);
} else if (atdState[position].equals("U")) {
atdButton.getBackground().setColorFilter(0xFFFF0000,
PorterDuff.Mode.MULTIPLY);
} else {
atdButton.getBackground().clearColorFilter();
}
atdButton.setFocusable(true);
atdButton.setClickable(true);
atdButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
Button atdButton = (Button) view
.findViewById(R.id.attendbutton);
String test = atdButton.getText().toString();
if (test.equals(" ")) {
atdButton.setText("P");
atdState[pos] = "P";
atdButton.getBackground().setColorFilter(0xFF00FF00,
PorterDuff.Mode.MULTIPLY);
} else if (test.equals("P")) {
atdButton.setText("T");
atdState[pos] = "T";
atdButton.getBackground().setColorFilter(0xFFFFFF00,
PorterDuff.Mode.MULTIPLY);
} else if (test.equals("T")) {
atdButton.setText("E");
atdState[pos] = "E";
atdButton.getBackground().setColorFilter(0xFFFF6600,
PorterDuff.Mode.MULTIPLY);
} else if (test.equals("E")) {
atdButton.setText("U");
atdState[pos] = "U";
atdButton.getBackground().setColorFilter(0xFFFF0000,
PorterDuff.Mode.MULTIPLY);
} else if (test.equals("U")) {
atdButton.setText("P");
atdState[pos] = "P";
atdButton.getBackground().setColorFilter(0xFF00FF00,
PorterDuff.Mode.MULTIPLY);
}
}
});
return (row);
}
}
我使用setText并将我的按钮着色你想要setChecked或其他一些,但希望这会指向正确的方向。