6

enter image description herecome aggiungere un listener per caselle di controllo in una vista adattatore, Android, ArrayAdapter, onCheckedChanged, OnCheckedChangeListener

Ho un listView che per mezzo di un ArrayAdapter è popolato da piccole viste XML sub. ogni piccola vista ha solo due cose all'interno, una casella di controllo e un'etichetta di stringa accanto ad essa.

voglio impostare un listener onCheckedChanged per acquisire l'evento del controllo dell'utente o deselezionando le caselle di controllo.

ad esempio l'ascoltatore mostrato qui:

listView.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 

@Override 
public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) { 

Toast.makeText(this, "box has been checked", Toast.LENGTH_SHORT).show(); 

} 

}

dove metto il codice ascoltatore? e come lo installo?

codice per l'ArrayAdapter:

public class MobileArrayAdapter extends ArrayAdapter<CheckBoxInfo>{ 
    CheckBoxInfo[] objects; 
    Context context; 
    int textViewResourceId; 

    public MobileArrayAdapter(Context context, int textViewResourceId, 
     CheckBoxInfo[] objects) { 
     super(context, textViewResourceId, objects); 
     this.context = context; 
     this.textViewResourceId = textViewResourceId; 
     this.objects = objects; 

    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     View row_layout_view = convertView; 


      if ((row_layout_view == null)){ 


       LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
       row_layout_view = inflater.inflate(R.layout.row_layout, null); 
      } 

      //CheckBoxInfo item = objects.get(position); // for arrayList 
      CheckBoxInfo item = objects[position]; 

      if(item != null){ 

      TextView textView = (TextView) row_layout_view.findViewById(R.id.textView1); 
      CheckBox checkBox = (CheckBox) row_layout_view.findViewById(R.id.checkBox1); 

      if(item !=null){ 
      textView.setText(item.checkBoxName); 
      checkBox.setChecked(item.checkBoxState); 
       } 
      } 
      return row_layout_view; 
    } 


} 

risposta

29

Non usare il tuo esempio listView.setOnCheckedChangeListener o onCheckedChanged codice.

Prima di tutto, per CheckBox, è necessario utilizzare setOnClickListener() anziché setOnCheckedChangeListener(). È possibile ottenere lo stato selezionato all'interno della funzione onClick().

In secondo luogo, posizionare il numero setOnClickListener() all'interno della funzione getView() dell'adattatore di elenco.

Esempio:

checkBox.setOnClickListener(new OnClickListener() { 
    @Override 
    public void onClick(View arg0) { 
     final boolean isChecked = checkBox.isChecked(); 
     // Do something here. 
    } 
}); 
+3

io non credo che questo funziona perché di opinioni riciclaggio ListView. Mentre scorri verso il basso e un convertView selezionato viene riciclato, la riga selezionata diventa deselezionata. Come fai ad aggirare questo? –

+4

Questo è un comportamento corretto. Quando una vista viene riutilizzata, tutti i suoi sottotitoli hanno le caratteristiche della vista senza significato che è stata riciclata. Pertanto, è necessario aggiornare tutte le viste e i loro attributi in 'getView()' ogni volta. Ciò include l'impostazione del valore CheckBox e il suo 'OnClickListener'. In breve, mantieni l'ascoltatore e aggiungi 'checkBox.setChecked()' per impostarlo sul valore atteso nel caso in cui la vista riciclata (o nuova) abbia un'impostazione diversa. –

1

Grazie David! per quanto riguarda il commento di HukeLau_DABA, l'ho risolto aggiornando l'oggetto della visualizzazione elenco con il valore CheckBox all'interno di OnClickListener(). Nel mio caso ho un elenco di luoghi, come si può vedere nel codice seguente:

holder.placeCheckBox.setOnClickListener(new View.OnClickListener() { 

     //please note that objPlace, position and holder must be declared 
     //as final inside the getView() function scope. 
      @Override 
      public void onClick(View arg0) { 
       final boolean isChecked = holder.placeCheckBox.isChecked(); 
       if (isChecked){ 
        objPlace.setItemChecked("yes"); 
       }else{ 
        objPlace.setItemChecked("no"); 
       } 

       placesList.set(position,objPlace); // updating the list with the updated object 

      } 
     }); 
1

non si riferiscono a "holder.placeCheckBox" nella vostra onClickListener, si dovrebbe fare riferimento alla vista che è passato da onClick e gettarlo ai casella di controllo in modo da codice dovrebbe essere simile a questo:

holder.placeCheckBox.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View arg0) { 
      boolean isChecked = ((CheckBox)arg0).isChecked(); 
      if (isChecked){ 
       objPlace.setItemChecked("yes"); 
      }else{ 
       objPlace.setItemChecked("no"); 
      } 

      placesList.set(position,objPlace); // updating the list with the updated object 

     } 
    }); 
0

si potrebbe provare questo:

holder.placeCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 
    @Override 
    public void onCheckedChanged(CompoundButton compoundButton, boolean b) { 
     Log.d(TAG, "onCheckedChanged: " + holder.placeCheckBox.getText() + " " + (b ? "selected":"deselected")); 
    } 
});