Reputation: 5537
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:
onCheckedChanged
listener, which allows the thumb to change position
as usual, but which sets the Switch's color to be the opposite of what it normally would be
(so that it doesn't change color), and toggles the serviceI'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
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
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:
Upvotes: 1