Controllo di una casella di controllo in listview rende disponibili anche altre caselle di controllo casuali

each volta che controlla una casella di controllo nella mia list, altre checkbox casuali vengono controllate troppo. Potrebbe essere dovuto al riciclaggio degli articoli da listview.

Ho anche provato a impostare android:focusable="false" nella casella di controllo nel mio layout come suggerito in alcuni luoghi, ma ancora non si chiama onListItemClick () per una row quando la sua casella di controllo è selezionata. Solo quando scatto da qualche altra parte viene chiamata.

  • Spostamento della cartella di configuration AVD predefinita (.android)
  • Scarica il contenuto quando l'applicazione viene aggiornata tramite il gioco google?
  • Cattura evento onTouch da genitore, gestirlo e passare ai bambini
  • getLastKnownLocation restituisce NULL utilizzando GPS_PROVIDER e NETWORK_PROVIDER
  • Cambiare il colore di background trasshiny di progressbar android
  • Come impostare un timer in android
  • Quello che voglio è che solo le caselle di controllo controllate dall'utente dovrebbero restare controllate finché l'utente non deseleziona.

    Dà sotto il codice che è completo e potrebbe essere eseguito direttamente.

    Codice attività- ProjActivity.java:

     public class ProjActivity extends ListActivity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); PackageManager pm = getPackageManager(); List<ApplicationInfo> packages = pm.getInstalledApplications(PackageManager.GET_META_DATA); final CopyOfMyCustomAdapter a = new CopyOfMyCustomAdapter(this, packages); getListView().setAdapter(a); }} 

    E infine, il file di layout personalizzato – testlayout.xml

     <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <CheckBox android:id="@+id/checkBox1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:text="CheckBox" android:focusable="false" /> <ImageView android:id="@+id/imageView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher" android:focusable="false" /> 

    UPDATE: Il mio PersonalAdapter dopo il suggerimento in una risposta qui sotto:

     public class MyCustomAdapter extends ArrayAdapter<ApplicationInfo> { private List<ApplicationInfo> appInfoList; private LayoutInflater mInflater; private PackageManager pm; ArrayList<Boolean> positionArray; private Context ctx; int[] visiblePosArray; private volatile int positionCheck; public MyCustomAdapter(Context context, List<ApplicationInfo> myList) { super(context, NO_SELECTION); appInfoList = myList; ctx=context; mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); pm = context.getPackageManager(); positionArray = new ArrayList<Boolean>(myList.size()); for(int i =0;i<myList.size();i++){ positionArray.add(false); } } @Override public int getCount() { // TODO Auto-generated method stub return appInfoList.size(); } @Override public View getView(final int position, View convertView, ViewGroup parent) { View row = convertView; Holder holder = null; if(row==null){ row = mInflater.inflate(R.layout.testlayout, null); // visiblePosArray[position%visiblePosArray.length]=position; holder = new Holder(); holder.appIcon = (ImageView)row.findViewById(R.id.imageView1); holder.ckbox =(CheckBox)row.findViewById(R.id.checkBox1); row.setTag(holder); } else { holder = (Holder) convertView.getTag(); } holder.ckbox.setFocusable(false); holder.appIcon.setImageDrawable(appInfoList.get(position).loadIcon(pm)); holder.ckbox.setChecked(positionArray.get(position)); holder.ckbox.setText(appInfoList.get(position).loadLabel(pm)); holder.ckbox.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if(isChecked ){ System.out.println(position+"--- :)"); positionArray.add(position, true); }else positionArray.add(position, false); } }); return row; } static class Holder { ImageView appIcon; CheckBox ckbox; } 

    }

    Quando scorri su e giù vedo che gli indici casuali sono cambiati in vero nel mio Arraylist boolean quando sono in loro.

  • Come si può rilevare i gesti dello schermo al di fuori di una propria applicazione?
  • L'applicazione installata è di terze parti o less
  • Come testare lo schema di URL personalizzato in android
  • Calcola la differenza tra due volte android
  • Esempio di Gestione allarmi
  • Come modificare il colore corrente evidenziatore di tab in Android ViewPager?
  • 3 Solutions collect form web for “Controllo di una casella di controllo in listview rende disponibili anche altre caselle di controllo casuali”

    Quando una listview ricicla le viste, ricicla il suo stato attuale e gli ascoltatori ad esso collegati. Nel mio esempio, se la casella di controllo è stata selezionata e dispone di un set onCheckedChangeListener, entrambi resteranno parte della visualizzazione riciclata in base alla posizione. Quindi è nostra responsabilità ripristinare tutti gli stati e rimuovere gli ascoltatori precedenti.

    Così, quando stavo smontando la vista riciclata, l'ascoltatore onCheckedChange stava facendo esecuzione. una linea ha reso il programma perfettamente funzionante. L'ascoltatore è stato rimosso da:

     holder.ckbox.setOnCheckedChangeListener(null); 

    Di seguito è riportto il codice di lavoro di Adapter per le persone che potrebbero inciampare su questo problema:

     public class MyCustomAdapter extends ArrayAdapter<ApplicationInfo> { private List<ApplicationInfo> appInfoList; private LayoutInflater mInflater; private PackageManager pm; ArrayList<Boolean> positionArray; private Context ctx; int[] visiblePosArray; private volatile int positionCheck; public MyCustomAdapter(Context context, List<ApplicationInfo> myList) { super(context, NO_SELECTION); appInfoList = myList; ctx=context; mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); pm = context.getPackageManager(); positionArray = new ArrayList<Boolean>(myList.size()); for(int i =0;i<myList.size();i++){ positionArray.add(false); } } @Override public int getCount() { // TODO Auto-generated method stub return appInfoList.size(); } @Override public View getView(final int position, View convertView, ViewGroup parent) { View row = convertView; Holder holder = null; if(row==null){ row = mInflater.inflate(R.layout.testlayout, null); // visiblePosArray[position%visiblePosArray.length]=position; holder = new Holder(); holder.appIcon = (ImageView)row.findViewById(R.id.imageView1); holder.ckbox =(CheckBox)row.findViewById(R.id.checkBox1); row.setTag(holder); } else { holder = (Holder) convertView.getTag(); holder.ckbox.setOnCheckedChangeListener(null); } holder.ckbox.setFocusable(false); holder.appIcon.setImageDrawable(appInfoList.get(position).loadIcon(pm)); holder.ckbox.setChecked(positionArray.get(position)); holder.ckbox.setText(appInfoList.get(position).loadLabel(pm)); holder.ckbox.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if(isChecked ){ System.out.println(position+"--- :)"); positionArray.set(position, true); }else positionArray.set(position, false); } }); return row; } static class Holder { ImageView appIcon; CheckBox ckbox; } 

    }

    È necessario tenere traccia dello stato di controllo, perché ListView riutilizza le Views . così lo stato per la posizione uno precedentemente abilitato / disabilitato può apparire come per la posizione 7.

    Quindi, quello che devi fare è mantenere lo stato controllato in un arrays boolean o qualunque cosa preferisci.

    Prendi un livello boolean [] checkedState; inizializza in constructor, in base alle size dell'arrays di dati, puoi utilizzare ArrayList<Boolean> anche per le size dinamiche.

    impostare OnStateChangeListener ai tuoi CheckBoxes in getView() , each volta che è selezionato o getView() , prendi la posizione e salva nella checkedState di checkedState come segue:

     checkedState[position] = false;// or true accordingly 

    e quando si imposta altri dati per la View come TextView o ImageView per una posizione specifica, impostare lo stato controllato anche in questo modo:

     holder.appIcon.setImageDrawable(appInfoList.get(position).loadIcon(pm)); holder.ckbox.setChecked(checkedState[position]); 

    Una spiegazione e un esempio molto buoni:

    Galleria personalizzata di Android con casella di controllo nella griglia per select più

    Modifica: In realtà ciò che sta accadendo è, la posizione sta diventando buggy, per risolvere questo aggiungere queste righe:

     holder.ckbox.setText(appInfoList.get(position).loadLabel(pm)); holder.ckbox.setTag(String.valueOf(position)); // to properly track the actual position holder.ckbox.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton v, boolean isChecked) { int pos = Integer.parseInt( v.getTag().toString()) ; //to take the actual position positionArray.add(pos, isChecked); // we don't need to check whether it is true or false, however you can put if-else to debug the app. } }); 

    Una combinazione di questi due approcci ha funzionato per me:

    Ho un arrays boolean a livello di class che utilizzo per tenere traccia del valore delle caselle di controllo.

     boolean [] checkedItems = new boolean[listItems.size()]; 

    In getView ():

      public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = inflater.inflate(R.layout.menu_item_list_item, parent, false); holder = new ViewHolder(); holder.name = (TextView) convertView .findViewById(R.id.menuItemLargeName); holder.mainItemCheckBox = (CheckBox) convertView .findViewById(R.id.menuItemLargeCheckBox); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); // remove the listener so that it does not get attached to other chechboxes. holder.mainItemCheckBox.setOnCheckedChangeListener(null); //update the checkbox value from boolean arrays holder.mainItemCheckBox.setChecked(checkedItems[position]); } holder.name.setText(listItems.get(position).getName()); holder.mainItemCheckBox .setOnCheckedChangeListener(onCheckedListener); holder.mainItemCheckBox .setTag(R.id.menuItemLargeCheckBox, position); return (convertView); } 

    Nel mio OnCheckedChangeListener (): aggiorna l'arrays boolean.

      OnCheckedChangeListener onCheckedListener = new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { int position = (Integer) buttonView .getTag(R.id.menuItemLargeCheckBox); MenuItemObject menuItem = listItems.get(position); if (isChecked) { cartItems.add(menuItem); checkedItems[position] = true; } else { cartItems.remove(menuItem); checkedItems[position] = false; } } }; 
    L'Android è un fan Android di Google, tutto su telefoni Android, Android Wear, Android Dev e applicazioni Android Games e così via.