2012-04-15 10 views
4

私はカスタムのResourceCursorAdapterを使用してTextViewとCheckBoxを表示するListViewに取り組んでいます。 TextViewとCheckBoxは、Cursorから状態を取得します。私はそれにいくつかの問題を抱えていました。最も最近のことは、いくつかの行がスクロールするときに古いTextViewsのテキストがあり、いくつかのCheckBoxesが選択されていないときです。私は何が起こっているのかを見るためにログラインを追加しました。それはもっと混乱しています。リサイクルされたListViewアイテムに古いコンテンツが表示されないようにするにはどうすればよいですか?

@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

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

これは最もスムーズな処理方法ではないかと思いますが、これが私のやり方です。ボタンの状態情報を保持する配列を作成し、getViewメソッドで使用して、要素が画面外になっても状態が維持されるようにしました。私はいくつかの状態(テキストおよび色)を有することができる各行上のボタンでリストアダプタを持っている私のプロジェクトのいずれかから

例:私のsetTextと色付けを使用

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); 
    } 

}

私のボタンは、あなたが正しい方向にあなたを指し示してくれることを願っています。

+0

私は以前に行っていたbindViewメソッドにすべてのViewHeaderコードを投げることでアイテムを繰り返すという問題を解決しました。今私は以前の問題に戻ってきましたが、CheckBoxをクリックすると、画面上とデータベース内の状態が変わりますが、画面からスクロールして戻すと元の状態に戻ります。作成時と再描画時に状態を設定する方法はありますか? (アクティビティを終了し、戻ってくると変更が反映されます) –

+0

これは私の答えで示したコードです。項目の状態を保持する配列を作成し、bindViewを参照してください。私のコードを見ると、ボタンのテキストと色を、直接ではなく配列に基づいて割り当てることがわかります。変更を加えると配列が更新されたままになり、ビューをロードするたびに状態が適切に設定されます。 – Barak

関連する問題