Don Hatch
Don Hatch

Reputation: 5537

how to make a Switch control show that it's "turning on" or "turning off"?

Let's say I have a Switch controlling an android service: when the Switch is in its "on" state, it means the service is running, and when the Switch is in its "off" position, it means the service is not running. Furthermore when the user taps on the Switch, it should toggle the service (and therefore toggle the Switch's displayed state, since, as already stated, the Switch's displayed state is tracking the service's state).

Method #1: Give the Switch an onCheckedChanged listener that turns the service on or off depending on the new checked state.

I don't like method #1, because when the user turns on the service by tapping the Switch, I don't want it to look like it's on until the service actually starts, which may not be immediate (and it may not start successfully at all, but I'll ignore that possibility here for simplicity). Likewise, when the user turns the service off, I don't want the Switch to look like it's off until the service has actually shut down.

Method #2: Make it so tapping the Switch toggles the service without changing the displayed state, and only toggle the displayed state when notified that the service has successfully come up or down.

I don't like method #2 either (even if I knew how to implement it), because the user doesn't get immediate feedback that the tap was recognized, and furthermore if the service doesn't successfully change state, then there's no feedback at all. I consider that bad.

Method #3: Make it so tapping on the Switch immediately toggles the thumb position but not the color and toggles the service, and make the Switch's color track the service's actual state. So, the color changes may be delayed relative to the thumb position changes.

That means the Switch will have 4 possible visual states instead of 2:

I like the idea of Method #3. What is the cleanest way to implement it?

It seems to me that I will likely have to install two listeners:

I'm sure I can figure out how to implement the notification that the service has come up or down. And, notice that I'm not wanting to change the thumb position behavior from its default. So really I think all I need to know is: how do I temporarily change an "on" Switch to have the "off" color scheme, and vice versa?

I have the impression this may involve calls to one or more of Switch's methods setTint(), setTintList(), setTintMode(). But I'm not sure exactly what the calls would be.

I would also welcome any other good ideas of how to make a Switch give immediate feedback that it's "turning on" or "turning off" without immediately displaying as "on" or "off".

Upvotes: 1

Views: 150

Answers (2)

RaviTejaSiddabattuni
RaviTejaSiddabattuni

Reputation: 156

Where ever you want switch..use the following layout..

<FrameLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <android.support.v7.widget.SwitchCompat
            android:id="@+id/sw_compat"
            android:layout_width="100dp"
            android:layout_height="50dp"
            android:checked="false"
            />
        <LinearLayout
            android:id="@+id/ll_touch_interceptor"
            android:layout_width="100dp"
            android:layout_height="50dp"
            android:orientation="vertical">

        </LinearLayout>
    </FrameLayout>

Now coming to activity, you don't need any onCheckedChangeListeners..use below code..

sw_compat= (Switch) findViewById(R.id.sw_compat);
        ll_touch_interceptor= (LinearLayout) findViewById(R.id.ll_touch_interceptor);
        ll_touch_interceptor.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ProgressDialog dialog = new ProgressDialog(DummyDialog.this);
                if (sw_compat.isChecked())
                {
                    dialog.setMessage("Demolishing service");
                    dialog.show();
                    //write code to initiate service / operation
                    //whenever you got feedback that service got successfully initiated then check the switch
                    if (service_successfully_disabled) {
                        dialog.dismiss();
                        sw_compat.setChecked(false);
                    }
                    else
                        {
                            Toast.makeText(DummyDialog.this, "Sorry! Failed to stop service", Toast.LENGTH_SHORT).show();
                        }
                }
                else
                    {
                        dialog.setMessage("Initiating service");
                        dialog.show();
                        if (service_successfully_enabled) {
                            dialog.dismiss();
                            sw_compat.setChecked(true);
                        }
                        else
                        {
                            Toast.makeText(DummyDialog.this, "Sorry! Failed to start service", Toast.LENGTH_SHORT).show();
                        }
                    }
            }
        });

Upvotes: 0

chrjs
chrjs

Reputation: 2443

I kinda like your idea. I think setTintList will be your friend.

What you want to do is something like this:

int[][] states = new int[][] {
        new int[] {-android.R.attr.state_checked},
        new int[] {android.R.attr.state_checked},
};

int[] thumbColors = new int[] {
        Color.LIGHTBLUE,
        Color.BLUE,
};

int[] trackColors = new int[] {
        Color.YELLOW,
        Color.RED,
};

DrawableCompat.setTintList(DrawableCompat.wrap(yourSwitchCompatView.getThumbDrawable()), new ColorStateList(states, thumbColors));
DrawableCompat.setTintList(DrawableCompat.wrap(yourSwitchCompatView.getTrackDrawable()), new ColorStateList(states, trackColors));

With this code you can adjust the thumb/track colors programatically. You need to set different colors for each of your different state (as you mentioned). Depending on your state/callback received you want to change the colors accordingly. It should work like this.

Another idea could be:

  • Switch is deactivated
  • Tap on switch
  • Replace switch with loading indicator/spinner
  • On Callback Success: Display active spinner

Upvotes: 1

Related Questions