0

I'm trying to implement a settings activity in my android app where users can turn on and off the notification mode. To achieve that I'm using Switch Compat. Here is the layout. It's part of my activity layout.

 <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:orientation="horizontal"
    android:layout_marginStart="24dp"
    android:layout_marginTop="90dp"
    android:layout_marginEnd="16dp">

    <TextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="@string/notifications"
        android:layout_gravity="start|center"
        android:layout_weight="1"
        android:textSize="20sp"
        android:textStyle="bold"
        android:id="@+id/notifications"/>


    <android.support.v7.widget.SwitchCompat
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/notificationsSwitch"
        android:layout_gravity="end|center"
        android:theme="@style/SwitchTheme"/>

</LinearLayout>

Here is the function which is responsive for the switch compat.

SwitchCompat notificationsSwitch;
AlertDialog alertDialog;
AlertDialog.Builder builder;

 @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.activity_settings, container, false);
     notificationsSwitch = (SwitchCompat) view.findViewById(R.id.notificationsSwitch);

notificationsSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                if (!b) {
                    builder = new AlertDialog.Builder(getActivity());
                    builder.setMessage("Are you sure that you want to turn the Notifications off");
                    builder.setPositiveButton("Turn off ", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {
                            notificationsSwitch.setChecked(false);
                        }
                    });
                    builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {
                            notificationsSwitch.setChecked(true);
                        }
                    });
                    alertDialog = builder.create();
                    alertDialog.show();
                    alertDialog.setCancelable(false);
                    alertDialog.setCanceledOnTouchOutside(false);
                    alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(getResources().getColor(R.color.alertDialogPositiveButton));
                    alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(getResources().getColor(R.color.alertDialogNegativeButton));
                } else {
                    builder = new AlertDialog.Builder(getActivity());
                    builder.setMessage("Are you sure that you want to turn the Notifications on");
                    builder.setPositiveButton("Turn on ", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {
                            notificationsSwitch.setChecked(true);
                        }
                    });
                    builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {
                            notificationsSwitch.setChecked(false);
                        }
                    });
                    alertDialog = builder.create();
                    alertDialog.show();
                    alertDialog.setCancelable(false);
                    alertDialog.setCanceledOnTouchOutside(false);
                    alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(getResources().getColor(R.color.alertDialogPositiveButton));
                    alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(getResources().getColor(R.color.alertDialogNegativeButton));
                }
            }
        });

What I want to do ?

  • As I said this should give the users ability to turn on and off the notification.

What is wrong?

  • The code works fine except one bug and that bug is when user want to turn the notifications on for ex. and then change his mind and click Cancel on the dialog he will enter in a loop.

Why is this happening?

  • I have made the cancel to work on that way so if the user click Cancel the Switch Compat goes back to the previous position where it was before. But since I have method for that state so it triggers the other state and the user is in loop.

What i tried?

  • I tried by using switch but I can't pass the Boolean variable b.

  • I also tried using flag variable but i couldn't find the logic.

Does someone knows how I can overcome this. Thanks in advance.

Jovan
  • 306
  • 6
  • 20

4 Answers4

1

You can use a flag as class attribute that will set true when click option in the Dialog, like IsFromDialog.

then, inside the Onclick function in the dialogs, set IsFromDialog = true;

And finally, at the start of the onCheckChanged you do

If (!b && !IsFromDialog) { ... }

  • That is what i did plus I added an Runnable which will reset the flag if I wan to turn it on. Thanks a lot. – Jovan Feb 04 '18 at 16:18
0

The OnCheckChanged listener is fired once when the user clicks the switch, then it gets fired again when your dialog changes it back, hence the loop. Try using an OnTouchListener instead.

ZengoTim
  • 211
  • 2
  • 10
0

You can solve this by removing the OnCheckedChangeListener, then modifying the state of the SwitchCompat, and then re-adding the OnCheckedChangeListener. That way, nothing is listening when you modify the switch.

This will be easier to do if you refactor the code a little bit. First, you should extract the anonymous listener to a variable in your fragment. In other words, delete this bit:

notificationsSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
    ...
});

And add this (outside onCreateView()):

private CompoundButton.OnCheckedChangeListener listener = new CompoundButton.OnCheckedChangeListener() {
    ...
}

Now that you've done that, you can set it inside your onCreateView() like this:

notificationsSwitch = (SwitchCompat) view.findViewById(R.id.notificationsSwitch);
notificationsSwitch.setOnCheckedChangeListener(listener);

From here, the rest is easy. Go into all four positive/negative listeners, and make them look like this:

notificationsSwitch.setOnCheckedChangeListener(null);
notificationsSwitch.setChecked(true);
notificationsSwitch.setOnCheckedChangeListener(listener);
Ben P.
  • 52,661
  • 6
  • 95
  • 123
0

Easiest way to achieve the same functionality:

switchWIdget.setOnClickListener{view -> 
            val switchView = view as SwitchCompat
            when (switchView.isChecked) {
                false -> {
                    //do stuff for FALSE
                }
                true -> {
                   //do stuff for TRUE
                }
            }
        }
Androidz
  • 261
  • 2
  • 11