5

カスタム ResourceCursorAdapter を使用して TextView と CheckBox を表示する ListView に取り組んでいます。TextView と CheckBox は Cursor から状態を取得します。私はそれでいくつかの問題を抱えていました.最新のものは、スクロールすると古いTextViewからのテキストがいくつかの行にあり、チェックボックスが選択されるべきではないときに選択されていることです。何が起こっているのかを確認するためにログ行を追加しましたが、それは私をさらに混乱させました.

@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
4

1 に答える 1

1

問題を引き起こしているのはビューのリサイクルです。

これが最もスムーズな処理方法かどうかはわかりませんが、これが私が行った方法です。ボタンの状態情報を保持する配列を作成し、それをgetViewメソッドで使用して、要素が画面外に出ても状態が維持されるようにしました。

私のプロジェクトの1つからの例では、各行にいくつかの状態(テキストと色)を持つことができるボタンを備えたリストアダプターがあります。

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などを使用しますが、これで正しい方向が示されることを願っています。

于 2012-04-15T01:15:48.230 に答える