我一直在堆栈上寻找很多指南、教程和答案,但我仍然无法弄清楚这一点。
我有一个自定义的可绘制状态。如果我单击 a 中的一行ListView
,它将突出显示并更新数据库中的此信息。(已经执行了一项任务(习惯))。在我开始滚动之前,一切都很好。我了解到,它需要覆盖该getView()
方法,可能还有getItemViewType()
with getViewTypeCount()
。
如何正确地做到这一点?我的 HabitsCursorAdapter 代码与 getView() 和其他提到的方法目前看起来像这样。
public class HabitsCursorAdapter extends CursorAdapter {
private LayoutInflater inflater;
private Context context;
public static final int PERFORMED = 1;
public static final int NOT_PERFORMED = 0;
public HabitsCursorAdapter(Context context, Cursor c) {
super(context, c, 0);
inflater = LayoutInflater.from(context);
this.context = context;
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
String habitName = cursor.getString(cursor
.getColumnIndexOrThrow(SQLiteHabitHelper.COLUMN_NAME));
TextView habitNameTV = (TextView) view.findViewById(R.id.habit_name);
habitNameTV.setText(habitName);
/******************* OK ***********************/
ImageButton editButton = (ImageButton) view.findViewById(R.id.habit_edit_button);
Integer _id = cursor.getInt(cursor.getColumnIndexOrThrow(SQLiteHabitHelper.COLUMN_ID));
editButton.setTag(R.id.EDITED_HABIT_ID, _id);
view.setTag(_id);
editButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent(HabitsCursorAdapter.this.context,
HabitDetailActivity.class);
i.putExtra("_id", (Integer) v.getTag(R.id.EDITED_HABIT_ID));
HabitsCursorAdapter.this.context.startActivity(i);
}
});
ImageButton deleteButton = (ImageButton) view
.findViewById(R.id.habit_history_button); // NEED TO REWRITE TO DELETING BUTTON
deleteButton.setTag(R.id.EDITED_HABIT_ID, _id);
deleteButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//itemized due debugging issue
HabitListActivity hla = ((HabitListActivity) HabitsCursorAdapter.this.context);
Object o = v.getTag(R.id.EDITED_HABIT_ID);
Integer i = (Integer) o;
long l = i.longValue();
hla.delete(l);
}
});
/******************* OK **********************/
HabitListItemView hv = (HabitListItemView) view;
hv.setHabitPerformed(
(1 == cursor.getInt(cursor.getColumnIndexOrThrow(SQLiteHabitHelper.COLUMN_PERFORMED))) ? true : false
);
view.refreshDrawableState();
}
@Override
public View newView(Context context, Cursor c, ViewGroup container) {
HabitListItemView v = (HabitListItemView) inflater.inflate(
R.layout.habit_item_layout, container, false);
bindView(v, context, c);
return v;
}
@Override
public int getViewTypeCount() {
return 2;
}
@Override
public int getItemViewType(int position) {
Cursor c = (Cursor) getItem(position);
c.moveToPosition(position);
int value = c.getInt(c.getColumnIndexOrThrow(SQLiteHabitHelper.COLUMN_PERFORMED));
if(0 != value){
return PERFORMED;
}
return NOT_PERFORMED;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (!mDataValid) {
throw new IllegalStateException("this should only be called when the cursor is valid");
}
if (!mCursor.moveToPosition(position)) {
throw new IllegalStateException("couldn't move cursor to position " + position);
}
View v;
if (convertView == null) {
v = newView(mContext, mCursor, parent);
return v;
} else {
mCursor.moveToPosition(position);
HabitListItemView hv = (HabitListItemView) convertView;
int convertViewIsPerformed = hv.getHabitPerformed() ? 1 : 0;
int actualItemPerformed = getItemViewType(position);
if(actualItemPerformed == convertViewIsPerformed){
v = convertView;
bindView(v, mContext, mCursor);
return v;
}else{
v = newView(mContext, mCursor, parent);
return v;
}
}
}
}
自定义行视图是:
public class HabitListItemView extends RelativeLayout {
private static final int[] STATE_HABIT_PERFORMED = { R.attr.state_habit_performed };
private boolean performed;
public HabitListItemView(Context context) {
this(context, null);
}
public HabitListItemView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
loadViews();
}
public HabitListItemView(Context context, AttributeSet attributeSet,
int defStyle) {
super(context, attributeSet, defStyle);
loadViews();
}
private void loadViews() {
setBackgroundResource(R.drawable.habit_list_item_background);
}
@Override
protected int[] onCreateDrawableState(int extraSpace) {
if (performed) {
final int[] drawableState = super
.onCreateDrawableState(extraSpace + 1);
mergeDrawableStates(drawableState, STATE_HABIT_PERFORMED);
return drawableState;
} else {
return super.onCreateDrawableState(extraSpace);
}
}
public void setHabitPerformed(boolean performed) {
this.performed = performed;
refreshDrawableState();
}
public boolean getHabitPerformed() {
return performed;
}
}
和onListItemClick()
ListFragment 中的
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
HabitListItemView hv = (HabitListItemView) v;
ContentValues cv = new ContentValues();
String habitId = v.getTag().toString();
SQLiteDatabase db = dh.getWritableDatabase();
Cursor cPerfomed = db.query(SQLiteHabitHelper.TABLE_HABIT,
new String[]{SQLiteHabitHelper.COLUMN_ID, SQLiteHabitHelper.COLUMN_PERFORMED},
"_id = ?", new String[]{habitId}, null, null, null);
cPerfomed.moveToFirst();
int performed = cPerfomed.getInt(cPerfomed.getColumnIndexOrThrow(SQLiteHabitHelper.COLUMN_PERFORMED));
cPerfomed.close();
cv.put(SQLiteHabitHelper.COLUMN_ID, (Integer) v.getTag());
cv.put(SQLiteHabitHelper.COLUMN_PERFORMED, (performed == 0) ? 1 : 0);
db.update(SQLiteHabitHelper.TABLE_HABIT, cv, "_id = ?", new String[]{habitId});
db.close();
hv.setHabitPerformed((performed == 0) ? true : false);
}
关于如何以及何时调用覆盖方法的一个很好的彻底解释可能会帮助我解决这个问题。我认为 newView 和 bindView 仅由 getView 调用,因此我相信我可以通过覆盖的 getView 来控制它。但是 getItemViewType 和 getViewTypeCount 是由我没有实现的方法调用的,我不明白为什么以及如何使用结果。也许他们会导致问题。
如果需要更多代码,我会根据要求编辑我的帖子。
任何帮助将不胜感激!