Android Question Problems getting label height measured correctly

kostefar

Active Member
Licensed User
Longtime User
Dear All,

I´ve been playing around with creating a 9-patch drawable, and use it as a label background. The label should stretch to fit the text inside of it, and for that I´ve found 3 different methods in the forum.
I´ve attached a small app that´ll demonstrate the results of each method. It keeps writing the word test untill 85% of the screen width is reached, and then starts on a new line. All you need to do is keep clicking on one of the buttons at the bottom; each of them triggers one of the 3 methods. So for instance, to see what happens when using method one, click the first button over and over again to see what happens. Once you click another button, the process resets with the new method.
The first method is the most succesful one, with only one issue: The padding at the bottom of the label becomes more and more, the more the label grows. First it looks like this:

gU0L6dG.png


But then after some lines, we can see how much the lower padding has grown:

ilrvjeC.png


This in fact also happens if I do not load the 9 patch image on the button.
It also does this for the padding on the right edge (which happens for all methods btw), which can be seen while there´s still only the first line. It keeps on expanding.
The 2nd method makes the drawable too big - big enough for 3 lines - and won´t start expanding vertically till the 4th line is added.
The 3rd and last method doesn´t show the lines from 2nd and up till the line has been completed.

Does anyone have any good ideas to add here, so I can get things right?

Thanks in advance!
 

Attachments

  • Autodimension_methods.zip
    10.9 KB · Views: 183

kostefar

Active Member
Licensed User
Longtime User
1. It is very difficult to click on these small buttons.
2. You can use the Padding property to access the padding values.

You should use StringUtils.MeasureMultilineTextHeight for multiline text. This is the most accurate method.

Thanks Erel,

I´ve modified the code so that the buttons are easier to access.

I tried instead with
B4X:
Txtlabel.Height = Max(30dip,su.MeasureMultilineTextHeight(lblMeasure,Txtlabel.text)+Txtlabel.padding(1)+Txtlabel.Padding(3))
and also

B4X:
Sub getPaddingRight(v As View) As Int
    Dim jo = v As JavaObject
    'Return jo.RunMethod("getPaddingRight", Null)
    Return v.Padding(2)
End Sub

Sub getPaddingLeft(v As View) As Int
    Dim jo = v As JavaObject
   
    'Return jo.RunMethod("getPaddingLeft", Null)
    Return v.Padding(0)
End Sub

but the result is even worse. When you say it´s the most accurate, do you mean that it´s not accurate - just the most accurate?
 

Attachments

  • Autodimension_methods.zip
    10.9 KB · Views: 185
Upvote 0

kostefar

Active Member
Licensed User
Longtime User
Thanks Erel,

I´m gonna see if I can reproduce the exact way that customlist works and apply it to the labels here and get back.
 
Upvote 0

kostefar

Active Member
Licensed User
Longtime User
Ok, I´m a bit further now. The most accurate method I found for when having a 9 patch drawable loaded in the background is to fire this every time the label content is modified:
B4X:
    Dim r As Reflector, DrwRect As Rect
    r.Target = Txtlabel.background
    DrwRect.Initialize(0, 0, 0, 0)
    r.RunMethod4("getPadding", Array As Object(DrwRect), Array As String("android.graphics.Rect"))
    verticalpadding = DrwRect.Top + DrwRect.Bottom
    Txtlabel.Height = Max(20dip,su.MeasureMultilineTextHeight(Txtlabel,Txtlabel.text)+verticalpadding)



But, I still have a problem with the horizontalpadding, regardless of whether if I use a background or not. Try this simple code and see how more and more extra padding is added to the end of the first line. There´s not even horizontal padding added here in the code:

B4X:
#Region  Project Attributes
    #ApplicationLabel: B4A Example
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region


Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
    Dim su As StringUtils
    Private Txtlabel As Label
    Dim lblMeasure As Label
    Dim cnv As Canvas
    Dim verticalpadding As Int
    Dim horizontalpadding As Int
    Dim scaletype As Int
End Sub

Sub Activity_Create(FirstTime As Boolean)

    Dim pnl As Panel
    pnl.Initialize("")
    Dim btn2 As Button

    btn2.Initialize("btn2")


    btn2.Color = Colors.Yellow

    Activity.Color = Colors.LightGray
    Activity.AddView(btn2,5%x,90%y,40dip,40dip)
    Activity.AddView(pnl,0,0, 100%x, 100%y)
    Txtlabel.Initialize("")
    Txtlabel.Color = Colors.white
    Activity.AddView(Txtlabel,0,0,0,0)
    Txtlabel.Typeface = Typeface.DEFAULT
    Txtlabel.TextColor = Colors.black
    cnv.Initialize(pnl)


End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub btn2_click
    resize_and_addtxt

    Dim r As Reflector, DrwRect As Rect
    r.Target = Txtlabel.background
    DrwRect.Initialize(0, 0, 0, 0)
    r.RunMethod4("getPadding", Array As Object(DrwRect), Array As String("android.graphics.Rect"))
    verticalpadding = DrwRect.Top + DrwRect.Bottom
    Txtlabel.Height = Max(20dip,su.MeasureMultilineTextHeight(Txtlabel,Txtlabel.text)+verticalpadding)
 
End Sub

Sub resize_and_addtxt
 
 
    Txtlabel.text = Txtlabel.text & " test"

 
If (cnv.MeasureStringWidth(Txtlabel.text,Txtlabel.Typeface,16)> 85%x) Then
        Txtlabel.Width = 85%x
    Else
 
     
        Txtlabel.Width = cnv.MeasureStringWidth(Txtlabel.text,Txtlabel.Typeface,16)
        End If
End Sub

EDIT: I figured it out, simpler than I thought. In activity_create, I was missing a declaration of the font size:
B4X:
Txtlabel.TextSize = 16
The default is 14, but the measuring is assuming the font size is 16.

01AF9Fg.png
 
Last edited:
Upvote 0
Top