Android Tutorial StateListDrawable example

StateListDrawable is a drawable objects that holds other drawables. Based on the view's current state a child drawable is selected.
StateListDrawable holds a list of states. States can be "disabled", "enabled", "checked" and so on.
A state can also be a combination of other states (like enabled and pressed).

The StateListDrawable holds a list of states and drawables pairs. Whenever the view's state changes the list is scanned and the first item that matches the current state is chosen.
Matching means that all elements in the state item are included in the current state.
This means that an empty state item will match all current states.
The order of states added is very important as the first item matches will be chosen.

This example creates a ToggleButton and sets its two states (checked and unchecked) to two ColorDrawables.
B4X:
Sub Process_Globals

End Sub

Sub Globals

End Sub

Sub Activity_Create(FirstTime As Boolean)
    Dim tb As ToggleButton
    tb.Initialize("") 'no events will be caught
    Dim checked, unchecked As ColorDrawable
    checked.Initialize(Colors.Green, 10dip)
    unchecked.Initialize(Colors.Red, 10dip)

    Dim sld As StateListDrawable
    sld.Initialize
    sld.AddState(sld.State_Checked, checked)
    sld.AddState(sld.State_Unchecked, unchecked)
    tb.Background = sld
    tb.Checked = True
    tb.TextColor = Colors.Blue
    tb.TextSize = 20
    tb.Typeface = Typeface.DEFAULT_BOLD
    Activity.AddView(tb, 100dip, 100dip, 100dip, 100dip)
End Sub
Note that in this case the order is not important as no state is contained in another.

state_list1.png


state_list2.png
 

walterf25

Expert
Licensed User
Longtime User
Hi Erel, i'm trying the SwitchView on my LG G3 running version L, i noticed that the text when the switch is either ON or OFF doesn't appear when testing on L version, is there a solution to fix this?

Thanks,
Walter
 

luisftv

Member
Licensed User
Longtime User
On post #20, why are all the colors specified as BLACK in the "Public Sub CreateButtonColor..." section?
B4X:
    drwFocusedColor.Initialize2(FocusedColor, 5, 0, Colors.Black)
    drwEnabledColor.Initialize2(EnabledColor, 5, 0, Colors.Black)
    drwDisabledColor.Initialize2(DisabledColor, 5, 0, Colors.Black)
    drwPressedColor.Initialize2(PressedColor, 5, 0, Colors.Black)

I tried assigning Blue (or another color) to all three states and still works, why?



Also, in the...

B4X:
Sub Activity_Create(FirstTime As Boolean)

   Help.Background = CreateButtonColor(Colors.LightGray, Colors.DarkGray, Colors.White, Colors.Black)

Why is it that specifying different colors here does overrides the "BlacK" in the previous section?

I tried only with the word "Colors" and nothing else (like .Blue, .Red, etc) in either section and then it won't compile. If I left only "Colors" in the Public Sub and then I typed Colors.Black, etc, it did not work, or vise verse. Why is that? In my non-programming mind (but I'm trying to self teach me, with this forums' help) seems like a redundancy... is it not? If not, what's the explanation for the redundancy?

Thanks in advanced.
 
Last edited:

RandomCoder

Well-Known Member
Licensed User
Longtime User
B4X:
drwFocusedColor.Initialize2(FocusedColor, 5, 0, Colors.Black)
    drwEnabledColor.Initialize2(EnabledColor, 5, 0, Colors.Black)
    drwDisabledColor.Initialize2(DisabledColor, 5, 0, Colors.Black)
    drwPressedColor.Initialize2(PressedColor, 5, 0, Colors.Black)

I suppose the first place to start is to say "Colors" is a keyword, it's a way to access a list of colour constants... https://www.b4x.com/android/help/constants.html#colors
Try typing the word Colors followed by a period "." and you will see the choice of colours.
In the example code above there are actually two colours being set although maybe not obvious at first glance. "FocusedColor", "EnabledColor", "DisabledColor" and "PressedColor" are all being set when the function was called. "Colors.Black" is just the colour of the border. You can if you want have a different border colour for each of the states.

Why is it that specifying different colors here does overrides the "BlacK" in the previous section?

Maybe it is because you have called this after calling the previous function to apply a StateListDrawable to the background. It is possible to overwrite the background at any time you want to change it.

I tried only with the word "Colors" and nothing else (like .Blue, .Red, etc) in either section and then it won't compile. If I left only "Colors" in the Public Sub and then I typedColors.Black, etc, it did not work, or vise verse. Why is that? In my non-programming mind (but I'm trying to self teach me, with this forums' help) seems like a redundancy... is it not? If not, what's the explanation for the redundancy?

As mentioned, "Colors" is a keyword and expects you to choose one of the colour constants when using it.

Hope this has made things a little clearer.
 

luisftv

Member
Licensed User
Longtime User
Yes, you did make it clearer RamdomCoder.

As a matter of fact, your explanation just solved a dilemma I posted on another thread, about how to bring focus to a button on an Android TV or on phones using D-pads.

I will be posting the solution soon... in a few days, as soon as I have it clear. It is working now. I need to test it further for bugs and cosmetics.

Thank you, thank you, thank you, thank you... did I thank you? Thank you!
 
Last edited:

RandomCoder

Well-Known Member
Licensed User
Longtime User
As a matter of fact, your explanation just solved a dilemma I posted on another thread, about how to bring focus to a button on an Android TV or on phones using D-pads.

I will be posting the solution soon... in a few days, as soon as I have it clear. It is working now.
I was just having another look at this and was wondering how you were changing the Focus to each Button and the Panel. If fact I've had a rather nice idea. Rather than send this thread of track I'll post in your other thread :D
 

luisftv

Member
Licensed User
Longtime User
ok.

By the way, I'll share with you and every one else here how I managed to "show" which button is active on D-pad and Android TV, like the 2015 (or newer) Sony 4K Android TVs. It's working so far...

I'll go to the other thread and see what you posted there.

Thank you sir.
 
Last edited:

Dave O

Well-Known Member
Licensed User
Longtime User
I'm having trouble setting the Pressed state of a toggle button. (Unchecked and Checked states work just fine.)

Here's the code that generates the StateListDrawable that I use for the toggle button's background:

B4X:
Sub createButtonStateListDrawable(prefixArg As String) As StateListDrawable
   Dim bmd As BitmapDrawable
   Dim sld As StateListDrawable
   sld.Initialize
   
   bmd.Initialize(LoadBitmap(File.DirAssets, prefixArg & ".png"))     
   bmd.Gravity = Gravity.FILL
   sld.AddState(sld.State_Unchecked, bmd)

   bmd.Initialize(LoadBitmap(File.DirAssets, prefixArg & "-pressed.png"))     
   sld.AddState(sld.State_Pressed, bmd)
   sld.AddState(sld.State_Checked, bmd)
   
   Return sld
End Sub

Any idea why the Pressed state is not working? (i.e. no change when I touch-down on the button)
 

MaFu

Well-Known Member
Licensed User
Longtime User
I think it's the wrong order because Android uses the first matching state. If you press the button it is also unchecked. Try to initialize the unchecked state after the other states.
 

Dave O

Well-Known Member
Licensed User
Longtime User
I think it's the wrong order because Android uses the first matching state. If you press the button it is also unchecked. Try to initialize the unchecked state after the other states.

Bingo! You're right, when I added the Pressed state first, it worked properly. Thanks!
 
Top