Android Question Measuring height of text with non-ASCII characters

RB Smissaert

Well-Known Member
Licensed User
Longtime User
For this I use sUtils.MeasureMultilineTextHeight, which has always worked fine, but noticed it can give too small a height if the text contains
non-ASCII characters. Attached an image showing the troublesome text.
I have worked out a work-around (shown below), which seems to be working OK, but wonder what the standard way is to deal with this.

B4X:
Public Sub MeasureMultilineTextHeightLabel2(oParent As Object, tLabelProps As tViewProps) As Int
    
    Dim lblDummy As Label
    Dim iHt As Int
    Dim iDoubleLinebreaks As Int
    Dim dBytesDivChars As Double
    Dim dExtra As Double
    
    Dim arrBytes() As Byte = tLabelProps.strText.GetBytes("UTF8")
    dBytesDivChars = arrBytes.Length / tLabelProps.strText.Length
    
    If dBytesDivChars > 1 Then
        dExtra = dBytesDivChars - 1
        dBytesDivChars = 1 + dExtra * Enums.dNonASCIITextHeightCorrection 'default for Enums.dNonASCIITextHeightCorrection is 0.1
    End If
    'Log("dBytesDivChars: " & dBytesDivChars)
    
    'setup temp label
    lblDummy.Initialize("")
    lblDummy.TextSize = tLabelProps.fTextSize
    lblDummy.Typeface = tLabelProps.oTypeFace
    lblDummy.Height = tLabelProps.iHeight
    lblDummy.Width = tLabelProps.iWidth
    lblDummy.Padding = tLabelProps.arrPadding
    
    'note here the label height has to be doubled to avoid too small readings with char 9632 (??)
    '---------------------------------------------------------------------------------------
    mvPageRoot.AddView(lblDummy, 0, -1000, tLabelProps.iWidth, tLabelProps.iHeight) ' * 2)
    
    'MeasureMultilineTextHeight doesn't consider the padding!
    If tLabelProps.oCSB.IsInitialized Then
        lblDummy.Text = tLabelProps.oCSB
        iHt = sUtils.MeasureMultilineTextHeight(lblDummy, tLabelProps.oCSB) + tLabelProps.arrPadding(1) + tLabelProps.arrPadding(3)
    Else
        lblDummy.Text = tLabelProps.strText
        iHt = sUtils.MeasureMultilineTextHeight(lblDummy, tLabelProps.strText) + tLabelProps.arrPadding(1) + tLabelProps.arrPadding(3)
    End If
    
    iDoubleLinebreaks = CountStringInString(Chr(10) & Chr(10), tLabelProps.strText, False)
    
    iHt = iHt * dBytesDivChars + iDoubleLinebreaks * Enums.dCorrectDoubleLinebreakHeightFactor * (tLabelProps.fTextSize / 18)
    
    lblDummy.RemoveView

    Return iHt
    
End Sub

RBS
 

Attachments

  • Sub BuildKeyboard.zip
    256.9 KB · Views: 9

RB Smissaert

Well-Known Member
Licensed User
Longtime User
This is for displaying on the phone the relevant code (the Sub) directly from an error log.
So all the .bas files and also B4AProject.b4a.meta are in a folder on the phone and then if there is an error
one can see the relevant Sub where the error originated from. The files are parsed to just show the relevant Sub.
All quite helpful for the developer, not for the users.

So for example I have a .bas file to do with a custom keyboard, that has the following bit of code:

B4X:
Sub Class_Globals
    
    Public bKeyboardShowing As Boolean
    Private xui As XUI
    
    Private BMCE As BitmapCreatorEffects
    
    Public iCursorPos As Int
    
    Private bmpDeleteBack As Bitmap
    Private bmpDeleteForward As Bitmap
    Public bForwardDelete As Boolean
    Private bToggledDeleteButton As Boolean
    
    Private Const strLowerCase As String = $"1234567890qwertyuiopasdfghjkl♦♦zxcvbnm♦♦, .♦"$
    Private Const strUpperCase As String = $"1234567890QWERTYUIOPASDFGHJKL♦♦ZXCVBNM♦♦, .♦"$
    Private Const strSymbols1 As String = $"1234567890+×÷=/_€£¥₩!@#$%^&*()♦-'":;,?♦♦, .♦"$
    Private Const strSymbols2 As String = $"1234567890`~\|<>{}[]°•○●□■♤♡◇♧♦☆▪¤《》¡¿♦♦, .♦"$
    Private Const strNumeric As String = $"1234567890♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦♦-♦♦♦♦♦♦♦♦♦♦.♦"$
    
    Private cMP As B4XMainPage
    Private mEditText As B4XView
    Private miEditTextTag As Int
    Private miPageWidth As Int
    
    Private arrKBPanels(5) As Panel
      
End Sub

As it has non-ASCII characters in it sUtils.MeasureMultilineTextHeight doesn't produce the right height (too small).
As it is multi-line text it doesn't look I can use canvas MeasureText.
Maybe then my workaround (compare the number of bytes in the string with the string length) might for now be the best I can do.

RBS
 
Upvote 0
Top