Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android CheckBox do not listen OnCheckedChangeListener on restore fragment state

In my android app I have fragments & in one of fragment I have checkbox. This checkbox has listener like this, that shows alert dialog on check:

@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
      if (isChecked) {
           alertDialog.setPositiveButton(R.string.is_ok, new DialogInterface.OnClickListener() {
              public void onClick(DialogInterface dialog, int arg1) {
                  NItem item = new NItem();
                  item.isOk = 1;
                  setItem(item);
              }
           });
           alertDialog.setNegativeButton(R.string.is_not_ok, new DialogInterface.OnClickListener() {
              public void onClick(DialogInterface dialog, int arg1) {
                   NItem item = new NItem();
                   item.isOk = 0;
                   setItem(item);
              }
           });
           alertDialog.show();
       }
   }

When I check checkbox & go to other fragment & go back to fragment where this checkbox, the method onCheckedChanged is called again. I think it is because fragment restored from saved state. How to prevent this?

like image 531
Urma Avatar asked Jan 21 '26 23:01

Urma


2 Answers

You should detect when user touches your checkbox, and only handle onCheckedChanged() when the checkbox is touched.

Here is an example:

static Boolean isTouched = false;

yourCheckbox.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                isTouched = true;
                return false;
            }
        });


//Listen to checked change, but only if the toggle is touched, not when initializing the toogle
yourCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
    @Override
    public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
        if (isTouched) {
            //Do your things
            isTouched = false;
        }
    }
});
like image 115
matdev Avatar answered Jan 24 '26 16:01

matdev


In your onCheckedChanged(), check the fragment's isResumed() and only continue if it's true. That's much simpler than checking if the view is touched and will cover any cases where you want the listener to handle setChecked() calls. If you don't want the listener to pick up those calls, you can remove the listener before the call and add it back after.

isResumed() returns true if the fragment is in the resumed state (mState >= RESUMED). When onCheckedChanged() is called during the restore, it is in the ACTIVITY_CREATED state.

Here are the various states from the Fragment class:

INITIALIZING = 0;     // Not yet created.
CREATED = 1;          // Created.
ACTIVITY_CREATED = 2; // Fully created, not started.
STARTED = 3;          // Created and started, not resumed.
RESUMED = 4;          // Created started and resumed.
like image 22
Pilot_51 Avatar answered Jan 24 '26 16:01

Pilot_51