2017-08-20 3 views
0

私はTo-doリストアプリケーションを作成しています。リストアダプタでチェックボックスとそのリスナーを使用することに関して質問があります。リストビューの私の1行には、3つのTextViewと1つのチェックボックスが含まれています。私は、ユーザーがチェックボックスをチェックすると、1行の背景を変更したい。私はアダプタクラスにチェックボックスのリスナを置くべきだと読んだので、私はそれをやった。今問題があります - 私は私のリストビューにいくつかの行を追加し、それらのすべてがうまく動作するチェックボックスをオフにしたまま、行を追加すると、チェックボックスをチェックし、別のものを追加しようとエラーが発生しますAndroid:リストビューのチェックボックス(アダプタでOnCheckedChangeListenerを作成する方法)

のjava.lang.NullPointerException:nullのオブジェクト参照

に仮想メソッド「空android.view.View.setBackgroundColor(int型)」を呼び出すための試みは、以下の私のアダプターのコードです。何かアドバイスありがとうございます。私はちょうどAndroidプログラミングを始めているので、事前に理解していただきありがとうございます。

public class ToDoAdapter extends ArrayAdapter<ToDoTask> { 


ArrayList<ToDoTask> objects; 
Context context; 
int resource; 

public ToDoAdapter(@NonNull Context context, @LayoutRes int resource, @NonNull ArrayList<ToDoTask> objects) { 
    super(context, resource, objects); 
    this.objects = objects; 
    this.context = context; 
    this.resource = resource; 
} 

@Override 
public View getView(final int position, View convertView, final ViewGroup parent) { 
    View view = convertView; 
    ToDoHolder toDoHolder = null; 

    if (view == null) { 
     LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     view = layoutInflater.inflate(R.layout.row, parent, false); 

     toDoHolder = new ToDoHolder(); 
     toDoHolder.rowTitle = (TextView) view.findViewById(R.id.rowTitle); 
     toDoHolder.rowDesc = (TextView) view.findViewById(R.id.rowDesc); 
     toDoHolder.rowDate = (TextView) view.findViewById(R.id.rowDate); 
     toDoHolder.rowIsDone = (CheckBox) view.findViewById(R.id.rowCheckBoxDone); 

     toDoHolder.rowIsDone.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 
      @Override 
      public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { 
       if(checked){ 
        parent.getChildAt(position).setBackgroundColor(Color.parseColor("#8FE370")); 
       } 
       else 
        parent.getChildAt(position).setBackgroundColor(Color.WHITE); 
      } 
     }); 

     view.setTag(toDoHolder); 
    } else { 
     toDoHolder = (ToDoHolder) view.getTag(); 
    } 

    ToDoTask object = objects.get(position); 
    toDoHolder.rowTitle.setText(object.getTitle()); 
    toDoHolder.rowDesc.setText(object.getDescription()); 
    toDoHolder.rowDate.setText(object.getDate()); 
    toDoHolder.rowIsDone.setChecked(object.getDone()); 

    return view; 
} 

static class ToDoHolder { 
    TextView rowTitle; 
    TextView rowDesc; 
    TextView rowDate; 
    CheckBox rowIsDone; 
} 
} 

以下は、「AddToDoTask」クラスの単一行要素の詳細を取得するMainActivityクラスです。

public class MainActivity extends AppCompatActivity { 
private final int requestCode = 1; 
ArrayList<ToDoTask> lista = new ArrayList<>(); 
ToDoAdapter adapter = null; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    Button button = (Button) findViewById(R.id.buttonAdd); 
    ListView listView = (ListView) findViewById(R.id.listView); 

    adapter = new ToDoAdapter(this, R.layout.row, lista); 
    listView.setAdapter(adapter); 

    button.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View view) { 
      Intent intent = new Intent(getApplicationContext(), AddToDoTask.class); 
      startActivityForResult(intent, requestCode); 
     } 
    }); 

} 

@Override 
protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
    super.onActivityResult(requestCode, resultCode, data); 

    String title, description, date; 
    Boolean isDone; 

    if (requestCode == 1) { 
     if (null != data) { 
      title = data.getStringExtra("title"); 
      description = data.getStringExtra("description"); 
      date = data.getStringExtra("date"); 
      isDone = data.getBooleanExtra("done", false); 

      lista.add(new ToDoTask(title, description, date, isDone)); 
      adapter.notifyDataSetChanged(); 
     } 
    } 
} 

} enter image description here

+0

これは[アンドロイドに変更する]チェックボックスの背景色]を助けている場合(https://stackoverflow.com/questions/12889729/change-checkbox-background-color-in-android)を参照してくださいのような子ビューにアクセスすることができます。 – MikeT

+0

アダプタの中にアイテムを追加するコードを投稿してください –

答えて

1
public class ToDoAdapter extends ArrayAdapter<ToDoTask> { 
    private ArrayList<ToDoTask> objects; 
    private Context context; 
    private int resource; 
    private SparseBooleanArray checkedPositions = new SparseBooleanArray(); 

    public ToDoAdapter(@NonNull Context context, @LayoutRes int resource, @NonNull ArrayList<ToDoTask> objects) { 
     super(context, resource, objects); 
     this.objects = objects; 
     this.context = context; 
     this.resource = resource; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     ToDoHolder toDoHolder; 
     if (convertView == null) { 
      LayoutInflater layoutInflater = LayoutInflater.from(context); 
      convertView = layoutInflater.inflate(R.layout.row, parent, false); 
      toDoHolder = new ToDoHolder(); 
      toDoHolder.rowTitle = (TextView) convertView.findViewById(R.id.rowTitle); 
      toDoHolder.rowDesc = (TextView) convertView.findViewById(R.id.rowDesc); 
      toDoHolder.rowDate = (TextView) convertView.findViewById(R.id.rowDate); 
      toDoHolder.rowIsDone = (CheckBox) convertView.findViewById(R.id.rowCheckBoxDone); 
      convertView.setTag(toDoHolder); 
     } else { 
      toDoHolder = (ToDoHolder) convertView.getTag(); 
     } 
     toDoHolder.rowTitle.setTag(position); 
     toDoHolder.rowIsDone.setTag(convertView); 
     toDoHolder.rowIsDone.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 
      @Override 
      public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { 
       View view = (View) compoundButton.getTag(); 
       TextView title = (TextView) view.findViewById(R.id.rowTitle); 
       int pos = (int) title.getTag(); 
       if (checked) { 
        checkedPositions.put(pos, true); 
        view.setBackgroundColor(Color.parseColor("#8FE370")); 
       } else { 
        checkedPositions.put(pos, false); 
        view.setBackgroundColor(Color.WHITE); 
       } 
      } 
     }); 
     ToDoTask object = objects.get(position); 
     toDoHolder.rowTitle.setText(object.getTitle()); 
     toDoHolder.rowDesc.setText(object.getDescription()); 
     toDoHolder.rowDate.setText(object.getDate()); 
     toDoHolder.rowIsDone.setChecked(object.getDone() || checkedPositions.get(position)); 
     return convertView; 
    } 

    private class ToDoHolder { 
     private TextView rowTitle; 
     private TextView rowDesc; 
     private TextView rowDate; 
     private CheckBox rowIsDone; 
    } 
} 
+0

ありがとうございました。新しい行を追加する際の問題を解決しましたが、新しい行を追加すると、以前のチェックボックスのチェックボックスは緑の代わりに白い背景になります。私は、 "toDoHolder =(ToDoHolder)view.getTag();"のように、私は別のケースでgetTag()を使用しなければならないと仮定します。 - そうですか?この要素でgetTagを使用するには? – Grzegorz

+0

上記のコードをif条件で移動し、上に貼り付けてください。doHoHolder.rowIsDone.setChecked(object.getDone()); – prakash

+0

あなたは上記の投稿のコード全体を意味しますか?私はそれをしましたが、私は新しい行を追加するときに背景がまだ緑から白に変わります。 – Grzegorz

0

あなたのrow xmlファイルにレイアウトを追加し、toDoHolderでレイアウトを入れて、ちょうどレイアウトの背景色を変更する必要があります。あなたは

layout.findViewByID(int ID); 
関連する問題