Android Code Snippet CSBuilder with leading margin

B4X:
Sub Activity_Create(FirstTime As Boolean)
   Activity.LoadLayout("Layout")
   Sleep(0)
   Dim cs As CSBuilder
   cs.Initialize
   CallSub3(Me, "AddLeadingMarginSpan", cs, Array As Int(0dip, 30dip))
   cs.Append("1) First do text text text, text text text text text text text").PopAll
   CallSub3(Me, "AddLeadingMarginSpan", cs, Array As Int(0dip, 30dip))
   cs.Append(CRLF).Append("2) Second do text text text, text text text text text text text").PopAll
   Label1.Text = cs
End Sub

Sub AddLeadingMarginSpan(cs As Object, FirstAndRest() As Int)
   Dim span As JavaObject
   span.InitializeNewInstance("android.text.style.LeadingMarginSpan.Standard", Array(FirstAndRest(0), FirstAndRest(1)))
   Dim jo As JavaObject = cs
   jo.RunMethod("open", Array(span))
End Sub

SS-2018-03-09_08.33.33.png


You must use CallSub to call AddLeadingMarginSpan due to the way CSBuilder is implemented. The Sleep(0) is required if you want to call it from Activity_Create as otherwise the CallSub will be ignored (the activity is considered paused at that point).

The two numbers passed to AddLeadingMarginSpan are the first line margin and the other lines margin.
Note that in this example I've added two spans. One for each point.
 

fredo

Well-Known Member
Licensed User
Longtime User
Thanks for the snippet! It is very useful for structured text output.

Oh, and this was an eyeopener, since I wasn't aware of:
...Sleep(0) is required if you want to call it from Activity_Create...

My ignorance regarding
...(the activity is considered paused at that point)...
might be the cause for some quirky effects I had once in a while over the last years...
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
Experts tip:

Why is CallSub required here?
CSBuilder is implemented as an object wrapper. It inherits from AbsObjectWrapper<SpannableStringBuilder>.

We need to call the wrapper 'open' method.
If we try to get a reference to cs directly:
B4X:
Dim jo As JavaObject = cs
'Or:
Dim o As Object = cs
Log(GetType(o)) 'SpannableStringBuilder
It will return the wrapped SpannableStringBuilder. In most cases we are interested in the wrapped object, however in this specific case we need the wrapper itself.
The only way to get a reference to the wrapper itself is by calling a method with CallSub where the parameter type is Object:
B4X:
Sub AddLeadingMarginSpan(cs As Object, FirstAndRest() As Int)
Now cs points to the wrapper.
B4X:
Log(GetType(c)) 'CSBuilder
 
Top