Android Question Long string space

mitsusdev

Member
Licensed User
Longtime User
If I have a string of many characters on some devices will not be seen on a single line,

how can I truncate based on the space it occupies?

for example

"aaaaa bbbbb ccccc ddddd eeeee ffffff ggggg hhhhh iiiiiii"

for first device i must truncate to
"aaaaa bbbbb ccccc ddddd eeeee ffffff"

for other device i must truncate to
"aaaaa bbbbb ccccc ddddd eeeee ffffff ggggg hhhhh"

how can i calculate this ?

Thanks
 
Last edited:

RandomCoder

Well-Known Member
Licensed User
Longtime User
Upvote 0

mitsusdev

Member
Licensed User
Longtime User
function ThimWith work fine with label set to designer, but with label set to run time it return this error

java.lang.RuntimeException: Object should first be initialized (Typeface)

on

width = c.MeasureStringWidth(Text, Style, Size)


Label3.Initialize("View")
Panel1.AddView(Label3,80dip,52dip,LabelWidth,30dip)
Label3.Text="djdj djdjdjd djdjdjdj jejejejr rfjffj rjr rjr"
LabelNew.Text = TrimWidth(Label3.Text, Label3.Typeface, Label3.TextSize, LabelWidth)

Why ?
 
Upvote 0

RandomCoder

Well-Known Member
Licensed User
Longtime User
At a guess it's because you have not explicitly set the typeface of your label (although I would have expected it to return the default value).
Try adding this line before you set Label3.Text....
B4X:
Label3.Typeface = Typeface.DEFAULT
Alternatively you could remove all references to the variable Style in my function, I only added it to demonstrate that different typefaces have an effect on the overall length of a string.

Kind Regards,
RandomCoder
 
Upvote 0

mitsusdev

Member
Licensed User
Longtime User
Thanks, now work fine.

but it too slow (15 seconds) with the simulator, with devide (nexus s) it's normal speed.

i run function for 28 strings.

for 56 string go to "
java.lang.OutOfMemoryError: bitmap size exceeds VM budget
"

why ?
 
Upvote 0

RandomCoder

Well-Known Member
Licensed User
Longtime User
This is probably getting a little out of my depth but at a guess it's because a new canvas is being created each time the function is called. As were not actually using the canvas other than to measure the string width I'm guessing that it can just be disposed. But this is where my knowledge is limited as the documentation does not list a dispose method for the canvas.
Maybe someone else from the community can offer some help with this?

In the meantime I'll have a play and see if I can come up with a solution.

Kind regards,
RandomCoder
 
Upvote 0

RandomCoder

Well-Known Member
Licensed User
Longtime User
Hi mitsusdev,

I've modified my original sample to create 1000 labels loaded into a scrollview and I don't get the out of memory error you've experienced. I've even tested it with upto 10,000 labels and still no error. I'm testing on a Galaxy S3 phone which is not as powerful as the Nexus and so I'm not sure what the problem could be?
Below is the sample code I've used (be warned that changing it to 10,000 labels creates a significant delay as I'm loading them all into the scrollview in one go)...
B4X:
#Region  Project Attributes
    #ApplicationLabel: Trim String Width 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.
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    'Activity.LoadLayout("Layout1")
    Activity.Initialize("Main")
    ' The long string which is going to be truncated 100 times
    Dim LongString As String
    LongString = "This very long line of text needs to be truncated to the width of the label regardless of which font type is used."

    ' Scrollview containing 100 truncated labels
    Dim sv As ScrollView
    sv.Initialize(Activity.Height)
    Activity.AddView(sv, 0, 0, 100%x, 100%y)
    Dim svPanel As Panel
    svPanel = sv.Panel

    ' Create 1,000 truncated labels
    Dim x, listBottom As Int
    listBottom = 0
    For x = 0 To 1000
        Dim lbl As Label
        lbl.Initialize("lbl")
        lbl.Tag = "lbl_" & x
        lbl.TextSize = 14
        svPanel.AddView(lbl, 0, listBottom, svPanel.Width, 40)
        lbl.Text = TrimWidth(LongString, Typeface.DEFAULT, lbl.TextSize, lbl.Width-30dip)
       
        listBottom = lbl.Top + 40dip
    Next
    sv.Panel.Height = listBottom
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub TrimWidth(Text As String, Style As Typeface, Size As Int, MaxWidth As Int) As String
    Return Text
    Dim c As Canvas
    Dim width As Int
    c.Initialize(Activity)
    width = c.MeasureStringWidth(Text, Style, Size)
    If width >= MaxWidth Then
        Do Until width < MaxWidth
            Text = Text.SubString2(0, Text.Length - 1)
            width = c.MeasureStringWidth(Text, Style, Size)
        Loop
        Return Text
    Else
        Return Text
    End If
End Sub

Please let me know how you get on.

Cheers,
RandomCoder
 
Upvote 0

mitsusdev

Member
Licensed User
Longtime User
Than
Hi mitsusdev,

I've modified my original sample to create 1000 labels loaded into a scrollview and I don't get the out of memory error you've experienced. I've even tested it with upto 10,000 labels and still no error. I'm testing on a Galaxy S3 phone which is not as powerful as the Nexus and so I'm not sure what the problem could be?
Below is the sample code I've used (be warned that changing it to 10,000 labels creates a significant delay as I'm loading them all into the scrollview in one go)...
B4X:
#Region  Project Attributes
    #ApplicationLabel: Trim String Width 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.
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    'Activity.LoadLayout("Layout1")
    Activity.Initialize("Main")
    ' The long string which is going to be truncated 100 times
    Dim LongString As String
    LongString = "This very long line of text needs to be truncated to the width of the label regardless of which font type is used."

    ' Scrollview containing 100 truncated labels
    Dim sv As ScrollView
    sv.Initialize(Activity.Height)
    Activity.AddView(sv, 0, 0, 100%x, 100%y)
    Dim svPanel As Panel
    svPanel = sv.Panel

    ' Create 1,000 truncated labels
    Dim x, listBottom As Int
    listBottom = 0
    For x = 0 To 1000
        Dim lbl As Label
        lbl.Initialize("lbl")
        lbl.Tag = "lbl_" & x
        lbl.TextSize = 14
        svPanel.AddView(lbl, 0, listBottom, svPanel.Width, 40)
        lbl.Text = TrimWidth(LongString, Typeface.DEFAULT, lbl.TextSize, lbl.Width-30dip)
     
        listBottom = lbl.Top + 40dip
    Next
    sv.Panel.Height = listBottom
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub TrimWidth(Text As String, Style As Typeface, Size As Int, MaxWidth As Int) As String
    Return Text
    Dim c As Canvas
    Dim width As Int
    c.Initialize(Activity)
    width = c.MeasureStringWidth(Text, Style, Size)
    If width >= MaxWidth Then
        Do Until width < MaxWidth
            Text = Text.SubString2(0, Text.Length - 1)
            width = c.MeasureStringWidth(Text, Style, Size)
        Loop
        Return Text
    Else
        Return Text
    End If
End Sub

Please let me know how you get on.

Cheers,
RandomCoder


Thanks

i have resolve speed and error with a one time create canvas object and pass to function as parameter
B4X:
Sub TrimWidth(CanvasText As Canvas, Text As String, Style As Typeface, Size As Int, MaxWidth As Int) As String
Dim Width As Int
   
   
   If Style.IsInitialized = False Then
       Style = Typeface.DEFAULT
   End If
   
   Return Text
   
   Width = CanvasText.MeasureStringWidth(Text, Style, Size)
   If Width >= MaxWidth Then
     Do Until Width < MaxWidth
       Text = Text.SubString2(0, Text.Length - 1)
       Width = CanvasText.MeasureStringWidth(Text, Style, Size)
     Loop
     Text = Text.SubString2(0, Text.Length - 3) & "..."
     Return Text
   Else
     Return Text
   End If
   
End Sub
 
Upvote 0

RandomCoder

Well-Known Member
Licensed User
Longtime User
Your solution is exactly what I would have tried if it were not for my sample working with well over the number of string you were trying. I'm glad you've found a working solution for yourself and thanks for informing us ;)

Cheers,
RandomCoder
 
Upvote 0
Top