My android app has permanent WebSocket connection to Server. There's also a switch that provides the ability to turn off that connection. So now switch has 2 colors. If switch is on then WS is connected and switch is green. If switch is off then WS is disconnected and switch is red.
So only user can change switch state on/off. But now lets assume that switch was on and internet went down. I want to show to user that state. So added 3rd state - yellow (which means smth is wrong)
my_layout.xml
<Switch
android:checked="true"
android:gravity="left"
android:text="Online"
android:thumb="@drawable/switch_thumb"
android:track="@drawable/switch_back"/>
switch_thumb.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid
android:color="@android:color/white"/>
<stroke android:width="4dp" android:color="@android:color/transparent" />
<size
android:width="24dp"
android:height="24dp"/>
</shape>
switch_back.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/toggle_on" android:state_checked="true" android:state_pressed="true"/>
<item android:drawable="@drawable/toggle_on" android:state_checked="true" android:state_focused="false"/>
<item android:drawable="@drawable/toggle_off" android:state_checked="false" android:state_pressed="true"/>
<item android:drawable="@drawable/toggle_off" android:state_checked="false" android:state_focused="false"/>
</selector>
switch_back_broken.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/toggle_broken" android:state_checked="true" android:state_pressed="true"/>
<item android:drawable="@drawable/toggle_broken" android:state_checked="true" android:state_focused="false"/>
<item android:drawable="@drawable/toggle_off" android:state_checked="false" android:state_pressed="true"/>
<item android:drawable="@drawable/toggle_off" android:state_checked="false" android:state_focused="false"/>
</selector>
toogle_on.xml/toogle_off.xml/toggle_broken.xml:
ovals of different colors: ON is green, OFF is red, broken is orange.
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="@android:color/transparent" />
<corners android:radius="15dp"/>
<solid
android:color="@color/colorCheckGreen"/>
<size
android:width="40dp"
android:height="24dp"/>
</shape>
Here's the implementation:
private Switch onlineSwitch;
int currentSwitchBack = R.drawable.switch_back;
@Subscribe
public void wsStatusChange(WsStatusChange event) {
boolean isOnline = WsStatusChange.Status.OPENED.equals(event.getStatus());
int newBackId = isOnline ? R.drawable.switch_back : R.drawable.switch_back_broken;
if (currentSwitchBack != newBackId) {
currentSwitchBack = newBackId;
onlineSwitch.setTrackDrawable(getResources().getDrawable(newBackId));
}
}
So the idea behind is to change background to switch_back_broken.xml
when websocket goes down. Note that this background has same red color for offline mode, the only thing that's different is yellow online color. So thus both backgrounds cover all possible situations.
Now to the issue:
When switch is on
and I change TrackDrawable
from switch_back.xml
(which is green) to switch_back_broken.xml
(which is yellow) the UI displays RED background (notice that switch is in state ON
), which should NEVER happen. Neither of my backgrounds contain red color for ON
switch state. But if I double click on switch (meaning just retrigerring layout) colors go back to normal.
I guess this behaviour comes from base state of switch, that's off by default. So switch
component is painted with wrong layout guessing that it should be initially in state of off
. Has anybody faced this issue?
Any suggestions how to come around? Any kind of help is appreciated!
Best regards,
I end up with ugly solution. Just manually retriggering
switch
:Note
block
is needed if you haveonCheckedChanged
listeners, so you just don't trigger them:I wonder if there's another way out. Maybe something like
requestLayout
or ...?