Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

onCheckedChanged called automatically

I have a switch in a recyclerview and data is displayed in the recyclerview after retrieving data from DB. When the recyclerview is opened I read DB and if a field in DB is "Y" I enable the switch or else I disable the switch. Now the problem is along with it the onCheckedchanged listener is also called, I want the onCheckedChanged to be called only when user sets the switch manually.

On opening the recyclerview below is executed:

holder.enabledisable.setChecked(messengerRecord.get_is_valid().equalsIgnoreCase("Y"));

ViewHolder class:

public class viewHolder extends RecyclerView.ViewHolder implements CompoundButton.OnCheckedChangeListener{
public SwitchCompat enabledisable;
 public viewHolder(View v) {
            enabledisable = (SwitchCompat) v.findViewById(R.id.enabledisable);
            enabledisable.setOnCheckedChangeListener(this);
...................................
...................................

OncheckedChanged method which is called when the recyclerView is just opened:

@Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            Log.v("ranjith","called oncheckedchanged");
            MessengerRecord rec;
            rec = dbHelper.getRecord(descview.getText().toString());
            switch (buttonView.getId()) {
                case R.id.enabledisable:
                    if (isChecked) {
                        rec.set_is_valid("Y");
                        dbHelper.updateRecord(rec);
                     }
}

In Layout file:

<android.support.v7.widget.SwitchCompat
    android:layout_marginRight="16dp"
    android:layout_marginEnd="16dp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:focusable="false"
    android:id="@+id/enabledisable"
    android:layout_alignRight="@+id/textview_to"
    android:layout_alignEnd="@+id/textview_to"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true"/>
like image 281
Psypher Avatar asked Dec 24 '14 20:12

Psypher


4 Answers

It's weird all of us have this problem but not official Google answer to this simple problem.

The MOST simple it's to check:

buttonView.isPressed()

If true, means the user clicked the view.

No global variables are needed.

like image 103
Sulfkain Avatar answered Nov 02 '22 11:11

Sulfkain


I've ended up using this subclass of SwitchCompat to avoid this issue. This way I don't need boilerplate code where I'm using this class. Whenever you need to change the checked without firing the listener, use setCheckedSilent instead of setChecked:

import android.content.Context;
import android.os.Parcelable;
import android.support.v7.widget.SwitchCompat;
import android.util.AttributeSet;

/**
 * Created by emanuel on 30/5/16.
 */
public class Switch extends SwitchCompat {

    private OnCheckedChangeListener listener;

    public Switch(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
        this.listener = listener;
        super.setOnCheckedChangeListener(listener);
    }

    @Override
    public void onRestoreInstanceState(Parcelable state) {
        super.setOnCheckedChangeListener(null);
        super.onRestoreInstanceState(state);
        super.setOnCheckedChangeListener(listener);
    }

    public void setCheckedSilent(boolean checked) {
        super.setOnCheckedChangeListener(null);
        super.setChecked(checked);
        super.setOnCheckedChangeListener(listener);
    }
}

onRestoreInstanceState was triggering the listening also, when set in the onViewCreated method and you are going back to a previous fragment. Hope it works for you!

like image 42
Emanuel Andrada Avatar answered Nov 02 '22 09:11

Emanuel Andrada


Try this

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

        if (buttonView.isPressed()) {
          ... //returns true, if user clicks the switch button        
        }}
like image 15
Shyam Kumar Avatar answered Nov 02 '22 09:11

Shyam Kumar


Since RecyclerView is recycling views, a previously attached OnCheckedChangeListener can be triggered when setting checked value for the Switch of the new item.

When binding new data to an item:

   switch.setOnCheckedChangeListener(null) // remove any existing listener from recycled view
   switch.isChecked = [true/false] // will no longer trigger any callback to listener
   switch.setOnCheckedChangeListener { btnView, isChecked ->
       // do exiting stuff
   }
like image 6
jayeffkay Avatar answered Nov 02 '22 11:11

jayeffkay