0

所以我写了一个自定义光标适配器来处理列表行的自定义布局。布局包括一个 ToggleButton、一个 ImageButton 和一个 TextView。TextView 数据来自名为 ALARM_TIME 的列,并且加载得很好。

然而,ToggleButton 引起了问题。它的状态来自名为 ALARM_ISACTIVE 的列,该列将是 1(对应于“on”)或 0(对应于“off”)。单击 ToggleButton 应相应地更新数据库中的相应行。

但是,无论出于何种原因,我的实际行为与此完全不同。

单击 ToggleButton 会触发我单击的行和列表的前两行的 OnCheckedChange 侦听器,无论我单击哪一行。此外,如果我检查一行,向下滚动,然后向上滚动,则该行的状态不会持续存在。

我不确定这里发生了什么,也不知道如何解释或修复它。

有人能帮我一下吗?

作为参考,这是我的光标适配器:

public class AlarmCursorAdapter extends SimpleCursorAdapter implements OnCheckedChangeListener {

private Context mContext;
private int mLayout;
private Cursor mCursor;
private int mIdIndex;
private int mAlarmIndex;
private int mIsActiveIndex;
private LayoutInflater mInflater;

public AlarmCursorAdapter(Context context, int layout, Cursor c,
        String[] from, int[] to, int flags) {
    super(context, layout, c, from, to, flags);
    Log.d("alarmAdapter", "calling constructor");
    this.mContext = context;
    this.mLayout = layout;
    this.mCursor = c;
    this.mIdIndex = c.getColumnIndexOrThrow(DailyAlarmTable.ALARM_ID);
    this.mAlarmIndex = c.getColumnIndexOrThrow(DailyAlarmTable.ALARM_TIME);
    this.mIsActiveIndex = c.getColumnIndexOrThrow(DailyAlarmTable.ALARM_ISACTIVE);
    this.mInflater = LayoutInflater.from(mContext);
    Log.d("alarmAdapter", "finishing constructor");
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    if(mCursor.moveToPosition(position)) {
        ViewHolder holder;
        final int fPosition = position;
        Log.d("AlarmCursorAdapter", "getView called for position " + fPosition);
        // If the view isn't inflated, we need to create it
        if(convertView == null) {
            Log.d("AlarmAdapter", "creating position " + fPosition);
            convertView = mInflater.inflate(mLayout, null);

            holder = new ViewHolder();

            holder.alarmView = (TextView) convertView.findViewById(R.id.alarmView);
            holder.discardButton = (ImageButton) convertView.findViewById(R.id.alarmDiscard);
            holder.isActiveToggle = (ToggleButton) convertView.findViewById(R.id.alarmToggle);

            convertView.setTag(holder);
        } else { // If the view is already inflated, we need to get it for the holder
            Log.d("AlarmAdapter", "recycling position " + fPosition);
            holder = (ViewHolder) convertView.getTag();
        }

        // Populate the views
        String alarmString = mCursor.getString(mAlarmIndex);
        int isActive = mCursor.getInt(mIsActiveIndex);
        final int id = mCursor.getInt(mIdIndex);
        holder.alarmView.setText(alarmString);
        if(isActive == 1) {
            holder.isActiveToggle.setChecked(true);
        } else {
            holder.isActiveToggle.setChecked(false);
        }

        holder.isActiveToggle.setOnCheckedChangeListener(new OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton button, boolean isChecked) {
                Log.d("ToggleListener", "Toggle for " + fPosition + " triggered");
                if(isChecked) {
                    Toast.makeText(mContext, "row " + fPosition + " is checked", Toast.LENGTH_SHORT).show();
                    // Change the value of ALARM_ISACTIVE in the cursor to 1
                    ContentValues newValues = new ContentValues();
                    newValues.put(DailyAlarmTable.ALARM_ISACTIVE, 1);
                    String selection = "(" + DailyAlarmTable.ALARM_ID + " = " + id + ")";
                    int rowsUpdated = 0;
                    rowsUpdated = mContext.getContentResolver().update(AlarmProvider.CONTENT_URI,
                            newValues, selection, null);

                } else {
                    Toast.makeText(mContext, "row " + fPosition + " is unchecked", Toast.LENGTH_SHORT).show();
                    // Change the value of ALARM_ISACTIVE in the cursor to 0
                    ContentValues newValues = new ContentValues();
                    newValues.put(DailyAlarmTable.ALARM_ISACTIVE, 0);
                    String selection = "(" + DailyAlarmTable.ALARM_ID + " = " + id + ")";
                    int rowsUpdated = 0;
                    rowsUpdated = mContext.getContentResolver().update(AlarmProvider.CONTENT_URI,
                            newValues, selection, null);
                }
            }
        });

    }
    return convertView;
}

static class ViewHolder {
    ToggleButton isActiveToggle;
    TextView alarmView;
    ImageButton discardButton;
}

@Override
public void onCheckedChanged(CompoundButton button, boolean isChecked) {
    // TODO Auto-generated method stub

}
}

这是来自我的内容提供商的 update() 方法。为了彻底起见,我将其包括在内,并且因为问题更糟糕(只要我单击任何行,行就会不断更新以相互响应),直到我发现我不应该调用 notifyChange():

@Override
public int update(Uri uri, ContentValues values, String selection,
        String[] selectionArgs) {
    int uriType = sUriMatcher.match(uri);
    SQLiteDatabase db = database.getWritableDatabase();
    int rowsUpdated = 0;
    switch(uriType) {
    case ALARMS:
        rowsUpdated = db.update(DailyAlarmTable.TABLE_ALARM,
                values,
                selection,
                selectionArgs);
        break;
    case ALARM_ID:
        String id = uri.getLastPathSegment();
        if(TextUtils.isEmpty(selection)) {
            rowsUpdated = db.update(DailyAlarmTable.TABLE_ALARM,
                    values,
                    DailyAlarmTable.ALARM_ID + "=" + id,
                    null);
        } else {
            rowsUpdated = db.update(DailyAlarmTable.TABLE_ALARM,
                    values,
                    DailyAlarmTable.ALARM_ID + "=" + id + " and " + selection,
                    selectionArgs);
        }
        break;
    default:
        throw new IllegalArgumentException("Unknown URI: " + uri);
    }
//      getContext().getContentResolver().notifyChange(uri, null);
    return rowsUpdated;
}
4

1 回答 1

0

结果我需要在自定义光标适配器中实现一个布尔数组来存储切换按钮的状态。

于 2013-09-18T17:32:29.967 回答