2011-08-15 17 views
7

私は最初のAndroidアプリケーションを作成していますが、私はGoogle上で答えが見つからない問題があります。Androidどのチェックボックスが選択されているかを知る方法

チェックボックス付きのアイテムのリストが必要です。アイテム自体とチェックボックスの両方をクリック可能にしたい。

public class MyItem extends ListActivity { 
     private ArrayList<MyItem> items; 
     public void onCreate(Bundle savedInstanceState) { 
      /* code which creates instances of MyItem and inserts them on the *list* variable */ 
     MyArrayAdapter adapter = new MyArrayAdapter(this, R.layout.my_item, list); 

     setListAdapater(adapter); 
     setContentView(R.layout.items_list); 
    } 
     public onListItemClick(ListView l, View v, int position, long id){ 
      //handles the click on an item 
     } 

    public class MyArrayAdapter extends ArrayAdapter<MyItem>{ 
     private MyItem item; 
     public MyArrayAdapter(Context context, int resourceId, ArrayList<MyItem> list){ 
      //code for the constructor 
     } 
     public getView(int position, View convertView, ViewGroup parent){ 
      convertView = inflater.inflate(resourceId, null); 


      this.item = list.get(position); 
      if (this.item == null) { 
       return convertView; 
      } 
      else{ 
       if (resourceId == R.layout.my_item) { 
        final CheckBox cb = (CheckBox)convertView.findViewById(R.id.checkbox); 

        if(cb != null){ 
         //initially 
         if(chosen) 
          cb.setChecked(true); 
         else 
          cb.setChecked(false); 
         //set listener 
         cb.setOnClickListener(new View.OnClickListener() { 
          @Override 
          public void onClick(View arg0) { 
           if(cb.isChecked()) 
            chosen = true; 
           else 
            chosen = false; 
          } 
         }); 
        } 
       } 
      return convertView; 
     } 
    }  
} 

選択した変数について心配する必要はありません。私はそれを単にコードに書いた。これは実際にはデータベース内の値に対応します。アイテムをクリックするだけでうまくいきます。私は、チェックボックスをクリックしたときしかし、何が起こるかは、このです:

  • 私は内部的にチェックされている
  • チェックボックスがオンに最後のものである(これはAndroidのUIの仕事である)選択表示されますクリックするチェックボックスつまり、私の画面に8つの項目が表示され、そのうちの1つをクリックすると(どちらの項目でも問題ありません)チェックが正しいチェックボックスに表示されますが、内部的には8番目の項目がチェックされます。

私があなたに提供できるお手伝いをお待ちしております。前もって感謝します。

答えて

6

実際には、chosenのバッキング実装が重要です。 Androidはリストビューでいくつかの最適化を行い、リストアイテムのビューを再利用して過剰なオブジェクトの作成やガベージコレクション(しばしばぎこちないスクロールにつながる)を避けることができます。そのため、関連する場合は常に、どのリストアイテムを使用しているかを正確に把握する必要があります。

たとえば、100個のリストアイテムがあるとします。あなたの画面はおそらくそれらのすべてを表示することはできません。一度に表示できるアイテムは10個だけです。したがって、これらの表示可能な項目を表示するために、10個のビュー(実際にビュー階層)が作成されます。次の10個のアイテムにスクロールすると、10個の新しいビュー(合計20個)を作成するのではなく、リストが1つしか作成されない場合があります(1つのアイテムの半分が上に表示され、画面の下部に合計11個のアイテムが表示されます)、残りのアイテムは以前作成したビューを再利用します。

だから、最初の画面を示す概念表は次のようになります。

 
Item  View 
------- -------- 
Item 1 View 1 
Item 2 View 2 
Item 3 View 3 
Item 4 View 4 
Item 5 View 5 
Item 6 View 6 
Item 7 View 7 
Item 8 View 8 
Item 9 View 9 
Item 10 View 10 

そして、10項目を下にスクロールした後、それはおそらくない正確に(少し、このように見えるかもしれませんが、これはあなたのアイデアを取得するために):

 
Item  View 
------- -------- 
Item 11 View 1 
Item 12 View 2 
Item 13 View 3 
Item 14 View 4 
Item 15 View 5 
Item 16 View 6 
Item 17 View 7 
Item 18 View 8 
Item 19 View 9 
Item 20 View 10 

それでは、あなたはここから収集できることはあなたの周りにスクロールすると、単一の特定のビューが異なる項目を表すことができるということです。つまり、イベントハンドラは、関連するアイテムをどのように見つけ出すかに、より動的に対応する必要があります。

これはあなたの背景を少し分けて、getViewメソッドの実装方法を変更できるようにすることです。実際の問題は次のとおりです。変数itemは、Adapterのスコープに含まれています。残念ながら、ここに投稿していないコードは、chosenに置き換えてitemを使用していると推測しています。アイテムビューが作成されるたびに、itemを設定します。つまり、最初の8つのビューが作成された後、itemがリストの8番目のアイテムに設定されます。チェックボックスをクリックすると、itemが使用されます。これはクリックしたリスト項目ビューに対応する項目ではなく、8番目の項目です。私はクラスレベルitem変数を取り除く得ている

public getView(int position, View convertView, ViewGroup parent){ 
     View view = convertView; 
     if (view == null) { 
      view = inflater.inflate(R.layout.my_item, null); 
     } 

     final MyItem item = list.get(position); 
     final CheckBox cb = (CheckBox)convertView.findViewById(R.id.checkbox); 
     // This stores a reference to the actual item in the checkbox 
     cb.setTag(item); 

     if(item.chosen) 
      cb.setChecked(true); 
     else 
      cb.setChecked(false); 

     //set listener 
     cb.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View view) { 
       // This gets the correct item to work with. 
       final MyItem clickedItem = (MyItem) view.getTag(); 
       if(cb.isChecked()) 
        clickedItem.chosen = true; 
       else 
        clickedItem.chosen = false; 
      } 
     }); 

     return view; 
    } 
} 

注:

は、ここで私がお勧めしたいgetViewための構造です。

+0

を試してみてください。 setTag/getTagは、ビューではなくチェックボックスで行う必要がありました。 D: –

+1

あなたが指摘したバグを修正するために更新されました。他の誰かがこのコード全体で発生した場合に備えて、更新されました。 – kabuko

0

MyItemオブジェクトにisChecked値を保存し、アダプタのgetViewメソッドのチェックボックスに明示的なチェックボックスをオンにする必要があります。 onCheckedChangedListenerを使用します。

+0

私はそれをします。 OnCheckedChangeListenerを試していたのでOnClickListenerを使用していますが、動作していなかったので、onClickを試しました。結果は同じでした。私の問題は変更を保存していないことです(リストの8番目の項目に変更が保存されます)。私の問題は、私が実際に第1などをクリックしているときに私が第8をクリックしているということです。 –

0

あなたの説明に従えば、リストがあり、リストの各行にチェックボックスとテキストビューがあるようです。私のアプリでは、CheckboxとTextViewの両方をクリック可能にしようとするのではなく、ListViewのonItemclickを使用することに似ています。ユーザーがリスト内の項目を押した場合、コード内でチェックボックスをオンまたはオフにすることができます。これは、ユーザーがボックスをチェックすることができる視覚的な印象を与えるが、実装が非常に簡単です。

+0

私はあなたの答えをよく理解していませんでしたが、@ kabukoの回答が問題を解決しました。とにかくありがとう:) –

2

は、それは1つの詳細を除いて魔法のように働いていたこの

public getView(int position, View convertView, ViewGroup parent){ 
    View view = convertView; 
    if (view == null) { 
     view = inflater.inflate(R.layout.my_item, null); 
    } 

    final MyItem item = list.get(position); 
    // This stores a reference to the actual item in the view 
    view.setTag(item); 

    final CheckBox cb = (CheckBox)convertView.findViewById(R.id.checkbox); 

    //set listener 
    cb.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View view) { 
      // This gets the correct item to work with. 
      final MyItem clickedItem = (MyItem) view.getTag(); 
      if(cb.isChecked()) 
       clickedItem.chosen = true; 
      else 
       clickedItem.chosen = false; 
     } 
    }); 


    cb.setChecked(item.chosen); 
    return view; 
} 
+0

+1素晴らしいと簡単な解決策 – Simmant

+0

なぜclickedItem.chosen = cb.isChecked()ですか? – cyroxis

関連する問題