Switch in adapter for a ListView

Jorge Ibañez picture Jorge Ibañez · Dec 18, 2014 · Viewed 10.6k times · Source

I have a ListView with an adapter which layout has a Switch, so every item in the lists has a switch.

I want to use this code:

mySwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() {
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        // do something, the isChecked will be
        // true if the switch is in the on position
    }
});

But I don't know WHERE to use it: In the Adapter class or in the List Containing class, and how could I do for knowing what item am I modifying when I toggle that switch, so I can modify it's properties.

Edit: This is the Adapter class with the method implemented. It runs everytime the method getView() is called, and not when it's supposed to run(When a switch is toggled), and Logs appear in the logcat but the object which switch is toggled is not modified, when I scroll down and scroll up, the switch goes back to its original state:

package com.nahue.actions;

import java.util.ArrayList;

import android.app.Activity;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;


/*@SuppressLint("ViewHolder") */public class AdapterActions extends ArrayAdapter<Action>{

    // our ViewHolder.
    // caches our TextView
    static class ViewHolderItem {
        TextView codigo;
        TextView accion;
        TextView evento;
        Switch UnSwitch;
    }

    Activity context;
    ArrayList<Action> listaActions;

    // Le pasamos al constructor el contexto y la lista de contactos
    public AdapterActions(Activity context, ArrayList<Action> listaActions) {
        super(context, R.layout.layout_adapter_actions, listaActions);
        this.context = context;
        this.listaActions = listaActions;




    }

    public View getView(final int position, View convertView, ViewGroup parent) {

        ViewHolderItem viewHolder;

        // Rescatamos cada item del listview y lo inflamos con nuestro layout
        //View item = convertView;
        //item = context.getLayoutInflater().inflate(R.layout.layout_adapter_actions, null);

        // well set up the ViewHolder
        viewHolder = new ViewHolderItem();

        if(convertView==null){

            // inflate the layout
            LayoutInflater inflater = ((Activity) context).getLayoutInflater();
            convertView = inflater.inflate(R.layout.layout_adapter_actions, parent, false);

            // well set up the ViewHolder
            viewHolder = new ViewHolderItem();
            viewHolder.codigo = (TextView) convertView.findViewById(R.id.codigo);
            viewHolder.accion = (TextView) convertView.findViewById(R.id.accion);
            viewHolder.evento = (TextView) convertView.findViewById(R.id.evento);
            viewHolder.UnSwitch = (Switch) convertView.findViewById(R.id.activa);

            // store the holder with the view.
            convertView.setTag(viewHolder);

        }else{
            // we've just avoided calling findViewById() on resource everytime
            // just use the viewHolder
            viewHolder = (ViewHolderItem) convertView.getTag();
        }

        Action a = new Action(0, 1, 1, true);
        Accion LaAccion = new Accion(0, "", "");
        Evento ElEvento = new Evento(0, "", "");

        //ACTIONS
                ActionsSQLite base = new ActionsSQLite(context, "Actions", null,1);
                SQLiteDatabase db1 = base.getReadableDatabase();
                db1 = context.openOrCreateDatabase("Actions",SQLiteDatabase.OPEN_READONLY, null);

                String query = "SELECT * FROM Actions WHERE Id = " + String.valueOf(position + 1);
                Cursor c1 = db1.rawQuery(query, null);

                try{
                    if(c1!=null){

                        int i = c1.getColumnIndexOrThrow("Id");
                        int j = c1.getColumnIndexOrThrow("IdAccion");
                        int k = c1.getColumnIndexOrThrow("IdEvento");
                        int l = c1.getColumnIndexOrThrow("Activa");
                        boolean esActiva;

                        //Nos aseguramos de que existe al menos un registro
                        while(c1.moveToNext()){
                            if (c1.getInt(l) == 0){
                                esActiva = false;
                            } else
                            {
                                esActiva = true;
                            }
                            //Recorremos el cursor hasta que no haya más registros
                            a = new Action(c1.getInt(i), c1.getInt(j), c1.getInt(k), esActiva);
                        }
                    }
                    else 
                        Toast.makeText(context.getApplicationContext(), 
                                  "No hay nada :(", Toast.LENGTH_LONG).show();
                  }
                  catch (Exception e){
                    Log.i("bdActions", "Error al abrir o crear la base de datos" + e); 
                  }

                  if(db1!=null){
                        db1.close();
                }   


        //EVENTOS
        EventosSQLite base2 = new EventosSQLite(this.context, "Eventos", null, 1);
        SQLiteDatabase db2 = base2.getReadableDatabase();
        db2 = context.openOrCreateDatabase("Eventos",SQLiteDatabase.OPEN_READONLY, null);

        String query2 = "SELECT * FROM Eventos WHERE Id = " + a.getIdEvento();
        Cursor c2 = db2.rawQuery(query2, null);
        try{
            if(c2!=null){

                int h = c2.getColumnIndexOrThrow("Id");
                int i = c2.getColumnIndexOrThrow("Nombre");
                int j = c2.getColumnIndexOrThrow("Descripcion");

                //Nos aseguramos de que existe al menos un registro
                while(c2.moveToNext()){
                    //Recorremos el cursor hasta que no haya más registros
                    ElEvento = new Evento(c2.getInt(h), c2.getString(i), c2.getString(j));
                }
            }
            else 
                Toast.makeText(context.getApplicationContext(), 
                      "No hay nada :(", Toast.LENGTH_LONG).show();
        }
        catch (Exception e){
            Log.i("bdEventos", "Error al abrir o crear la base de datos" + e); 
        }

        if(db2!=null){
            db2.close();
        }   
        //ACCIONES
        AccionesSQLite base3 = new AccionesSQLite(context, "acciones", null,1);
        SQLiteDatabase db3 = base3.getReadableDatabase();
        db3 = context.openOrCreateDatabase("Acciones", SQLiteDatabase.OPEN_READONLY, null);

        String query3 = "SELECT * FROM Acciones WHERE Id = " + String.valueOf(a.getIdAccion());
        Cursor c3 = db3.rawQuery(query3, null);
        try{
            if(c3!=null){

                int h = c3.getColumnIndexOrThrow("Id");
                int i = c3.getColumnIndexOrThrow("Nombre");
                int j = c3.getColumnIndexOrThrow("Descripcion");

                //Nos aseguramos de que existe al menos un registro
                while(c3.moveToNext()){
                    //Recorremos el cursor hasta que no haya más registros
                    LaAccion = new Accion(c3.getInt(h), c3.getString(i), c3.getString(j));
                }
            }
            else 
                Toast.makeText(context.getApplicationContext(), 
                      "No hay nada :(", Toast.LENGTH_LONG).show();
        }
        catch (Exception e){
            Log.i("bdAcciones", "Error al abrir o crear la base de datos" + e); 
        }

        if(db3!=null){
            db3.close();
        }

        // object item based on the position

        viewHolder.UnSwitch.setChecked(a.getActiva());
        // assign values if the object is not null
        if(a != null) {
            // get the TextView from the ViewHolder and then set the text (item name) and tag (item ID) values
            viewHolder.codigo.setText(String.valueOf(a.getId()));
            viewHolder.codigo.setTag(a.getId());
            viewHolder.accion.setText(LaAccion.getNombre());
            viewHolder.evento.setText(ElEvento.getNombre());
            viewHolder.UnSwitch.setChecked(a.getActiva());
        }

        viewHolder.UnSwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() {
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            //you can modify Action here.
                Log.e("Listener del switch", "Entró");
            listaActions.get(position).setActiva(isChecked);
            Log.e("Listener del switch", "Modificó la action en la lista del adapter");
            ActividadPrincipal.listaActions.get(position).setActiva(isChecked);
            Log.e("Listener del switch", "Modificó la action en la lista de la ActividadPrincipal");
            int isActiva;
            if(isChecked == true)
            {
                isActiva = 1;
                Log.e("Listener del switch", "isActiva = 1");
            } else
            {
                isActiva = 0;
                Log.e("Listener del switch", "isActiva = 0");
            }
            String query = "UPDATE Actions SET Activa = " + String.valueOf(isActiva) + " WHERE Id = " + String.valueOf(position);
            Log.e("Listener del switch", "query creado");
            ActionsSQLite helper1  = new ActionsSQLite(context, "Actions", null, 1);
            Log.e("Listener del switch", "Creo el helper");
            SQLiteDatabase db = helper1.getWritableDatabase();
            Log.e("Listener del switch", "obtenida la base escribible");
            db.execSQL(query);
            Log.e("Listener del switch", "Query ejecutado");
        }});



        return convertView; 
    }   
}

Answer

Jorge Iba&#241;ez picture Jorge Ibañez · Dec 18, 2014

Solved.

The problem with the OnCheckedChangeListener() is that it executes the method every single time you execute getView(). How did I solve it? Easy: I just used an onClickListener(), and the code is executed only when I click in the Switch.

Now this is the result:

viewHolder.isChecked1 = viewHolder.UnSwitch.isChecked();
        map.put(position, viewHolder.isChecked1);
        viewHolder.UnSwitch.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.e("OnClick", "Se clickeó");

                listaActions.get(position).setActiva(map.get(position));
                Log.e("Listener del switch", "Modificó la action en la lista de la ActividadPrincipal");
                int isActiva;
                if(map.get(position) == true)
                {
                    isActiva = 0;
                    Log.e("Listener del switch", "isActiva = 1");
                    map.put(position, false);
                } else
                {
                    isActiva = 1;
                    Log.e("Listener del switch", "isActiva = 0");
                    map.put(position, true);
                }
                String query = "UPDATE Actions SET Activa = " + String.valueOf(isActiva) + " WHERE Id = " + String.valueOf(position+1);
                Log.e("Consulta:", query);
                Log.e("Listener del switch", "query creado");
                Log.e("La position debería ser", String.valueOf(position+1));
                Log.e("Y el valor del map.get(position) es", String.valueOf(map.get(position)));
                ActionsSQLite helper1  = new ActionsSQLite(context, "Actions", null, 1);
                Log.e("Listener del switch", "Creo el helper");
                SQLiteDatabase db = helper1.getWritableDatabase();
                Log.e("Listener del switch", "obtenida la base escribible");
                db.execSQL(query);
                Log.e("Listener del switch", "Query ejecutado");
            }
        });