Android Question [Solved] StateListDrawable with B4XPages

Gavin

Member
Licensed User
Longtime User
I am converting an old project from an Activity based application, (five activities), to a B4XPages Project.
In one of the Activities, I had five buttons, defined in the designer, with a "StateListDrawable" attribute.
When running the application, if I changed the State of any of these buttons in code from, say, Enabled to Disabled, the background would change to the background appropriate to the selected state.
However, this is not the case in the B44XPages project.
When I change the state, the state does indeed change, but the background does not reflect the changed state.
If I change the initial state in the designer, then the buttons background does show the correct background for the selected state, but, again. not when I change the state in Code.
What am I missing?
 

josejad

Expert
Licensed User
Longtime User
Please, show some code or even better, upload a small B4XPages project with just the buttons showing your problem. It will be easier to help you.
 
Upvote 0

Gavin

Member
Licensed User
Longtime User
Pardon my ignorance.
I clicked "ide://run?File=%B4X%\Zipper.jar&Args=Project.zip" and created a Zip File.
Now, exactly which file/files do I need to attach, or do you upload the Folder and how.
Once again, sorry.
 
Upvote 0

klaus

Expert
Licensed User
Longtime User
Post the zip file.
Click on this button
1721386120793.png
to attach the zip file to your post.
 
Upvote 0

Gavin

Member
Licensed User
Longtime User
Hopefully all went well.
This simple project contains three buttons and a label.
If you "Rem Out" the three lines of code which resizes the Button Text, all works as expected.
Un-rem these lines of code, the Buttons still behave as they should, but their Backgrounds do not change.
It may be related to Spavlyuk's comments, but I am not sure.
This is only a "Hobby / Interest" for me. I have no formal training and am still trying to understand "Object Orientated Programming".
 

Attachments

  • B4XMainPage.bas
    1.6 KB · Views: 73
Upvote 0

Gavin

Member
Licensed User
Longtime User
Sorry Klaus, still learning.
I have attached two files, SizeToFit.Jar and SizeToFit.zip.
This was my first attempt at a Library.
 

Attachments

  • SizeToFit.jar
    1.9 KB · Views: 77
  • SizeToFit.zip
    12 KB · Views: 74
Upvote 0

klaus

Expert
Licensed User
Longtime User
Do you also have a SizeToFit.xml file ?
The content of SizeToFit.zip is what I had found but, as already said, the SizeToFit.bas file does not have the Ideal_Text_Size method.
The problem is in the code of this library, and without seeing the code it, it is impossible to help.
 
Last edited:
Upvote 0

Gavin

Member
Licensed User
Longtime User
Hopefully, I got it right this time. This is what happens when you are learning to compile a simple library and you do not use a unique name.
Indeed, SizeToFit.bas was not written by myself but, I used the same name. Foolish me.
The String Utilities Library is required for SizeToFit.xml.

You could be right Klaus, as I was no using this routine in the original Application.
I was however resizing the text in code, after loading the Layout and the buttons acted correctly.
 

Attachments

  • SizeToFit.xml
    1.8 KB · Views: 75
Last edited:
Upvote 0

klaus

Expert
Licensed User
Longtime User
I installed the two library files, but I get an error in this line:
B4X:
    Button1.TextSize = stf.Ideal_Text_Size(Button1.Text, Button1, 60, "S")
I do not know how you got the SizeToFit.jar and the SizeToFit.xml files, they are not generated from the SizeToFit.bas file.
And without seeing the code impossible to know what happens.
Anyway, I suppose that stf.Ideal_Text_Size adapts the text size to the Button or Label size.
In the attached project I added a routine to adapt the text size. And the StateListDrawable work.
 

Attachments

  • State List1.zip
    10.6 KB · Views: 71
Upvote 0

Gavin

Member
Licensed User
Longtime User
Klaus, thank you so much for you patience with me.
Hopefully, this time.
I included my SizetoFit routine as a module, not a library, in this zip file.
All going well, if you rem out the "Button1.TextSize = stf.Ideal_Text_Size(Button1.Text, Button1, 60, "S")" in each sub, the buttons work as they should.
"Un-rem" them, the button event still fires but, the state does not change.
 

Attachments

  • Project.zip
    25.2 KB · Views: 73
Upvote 0

Gavin

Member
Licensed User
Longtime User
Ok, I think I got It,
In order for the StateListDrawable to work, to put it in Layman's terms, the StateListDrawable must be the "Last Instructions" you give the View before using the View.
If you do something as simple as, say, changing the Text Size, then you must "Reinstate"(for want of a better term) the StateListDrawable, or else nothing happens.
Hopefully, the attached example will show this.
Run the application as is, all is fine.
Un-Rem the instructions at the bottom of Sub_B4XCreate, the problem reappears.
 

Attachments

  • State List.zip
    10.3 KB · Views: 68
Upvote 0

klaus

Expert
Licensed User
Longtime User
Now seeing the code I found the problem.
In the Ideal_Text_Size method a Canvas is assigned to the Button, and this new assignment overrides the StateListDrawable definition.
If you modify the Ideal_Text_Size method like below, commenting all lines concerned by the Canvas the Buttons behave as expected.

B4X:
Public Sub    Ideal_Text_Size(Text_to_Size As String, TestLabel As Label, InitialSize As Int, SorM As String) As Int

    Private TextSizeBasedOnHeight     As Int
    Private    TextSizeBasedOnWidth     As Int
    Private FontSizeWidth            As Int = InitialSize
    Private FontSizeHeight            As Int = InitialSize
    Private CorrectSize                As Int
'    Private CVS                      As Canvas
'    CVS.Initialize(TestLabel)
    Private Padding(4)                 As Int
    Padding = TestLabel.Padding

'    TextSizeBasedOnWidth = CVS.MeasureStringWidth(Text_to_Size, TestLabel.Typeface, FontSizeWidth)
'
'    Do Until TextSizeBasedOnWidth < TestLabel.Width-Padding(0)-Padding(2)
'        TextSizeBasedOnWidth = CVS.MeasureStringWidth(Text_to_Size, TestLabel.Typeface, FontSizeWidth)
'        FontSizeWidth = FontSizeWidth-1
'    Loop
   
    TestLabel.TextSize = FontSizeHeight
    TextSizeBasedOnHeight = su.MeasureMultilineTextHeight(TestLabel, Text_to_Size)
   
    Do Until TextSizeBasedOnHeight < TestLabel.Height-Padding(1)-Padding(3)
        FontSizeHeight = FontSizeHeight-1
        TestLabel.TextSize = FontSizeHeight
        TextSizeBasedOnHeight = su.MeasureMultilineTextHeight(TestLabel, Text_to_Size)
    Loop
   
'    If SorM = "S" Then
'        If FontSizeWidth <= FontSizeHeight Then
'            CorrectSize = FontSizeWidth
'        Else
'            CorrectSize = FontSizeHeight
'        End If
'    Else If SorM = "M" Then
        If FontSizeWidth >= FontSizeHeight Then
            CorrectSize = FontSizeWidth
        Else
            CorrectSize = FontSizeHeight
        End If
'    End If
   
    Return CorrectSize

End Sub

By the way, the routine I included in my test project does the same.
 
Upvote 1

Gavin

Member
Licensed User
Longtime User
Well, once again, thank you very much Klaus for your time and patience.
I would never have worked this one out by myself.
I won't say it is obvious but, it makes perfect sense.
Of cause, I tried it, and it worked.
Also, it had nothing to do with B4XPages.
 
Upvote 0
Top