Android Tutorial CharSequence / CSBuilder Tutorial

Status
Not open for further replies.
B4A v6.80 adds several new features related to the ability to format rich strings.

upload_2017-2-14_12-30-39-png.52855


CharSequence is a native interface in Android SDK. A String is one implementation of CharSequence.
There are other implementations of CharSequence that provide more features and allow us to format the string, add images and even make parts of the text clickable.

Starting from B4A v6.80 many methods accept CharSequence instead of String. Existing code will work properly as you can pass regular strings. However you can now also pass more interesting CharSequences.

Note to library developers, if your library makes calls to APIs that work with CharSequences then you should change your method signatures to expect CharSequence instead of String. This will allow developers to format the text.

There are two ways to create CharSequences: agraham's RichString library or the new CSBuilder object.

This tutorial covers the new CSBuilder object.
CSBuilder is similar to StringBuilder. Instead of building strings, it builds CharSequences that include style information.

Using it is quite simple.
B4X:
Dim cs As CSBuilder
Label1.Text = cs.Initialize.Color(Colors.Red).Append("Hello World!").PopAll
SS-2017-02-15_14.35.59.png


Almost all methods of CSBuilder return the object itself. This allows us to chain the method calls.
Text is always appended with the Append method.
There are various attributes that can be set. Setting an attribute marks the beginning of a style span.
Calling Pop ends the last span that was added (and not ended yet).
Calling PopAll ends all open spans. It is convenient to always call PopAll at the end to ensure that all spans are closed.

B4X:
'example of explicitly popping an attribute:
Label1.Text = cs.Initialize.Color(Colors.Red).Append("Hello ").Pop.Append("World!").PopAll
SS-2017-02-15_14.40.34.png


B4X:
'It doesn't matter whether the methods are chained or split into several lines:
Dim cs As CSBuilder
cs.Initialize.Color(Colors.Red).Append("Hello ")
cs.Bold.Color(Colors.Green).Append("Colorful ").Pop.Pop 'two pops: the first removes the green color and the second removes the bold style
cs.Append("World!").PopAll
Label1.Text = cs
'can also be set as the activity title
Activity.Title = cs
'and Toast messages and in other places...
ToastMessageShow(cs, True)
SS-2017-02-15_14.46.12.png


Using the new Typeface.FONTAWESOME and MATERIALICONS

B4X:
Dim cs As CSBuilder
Label1.Text = cs.Initialize.Append("Text with FontAwesome: ").Typeface(Typeface.FONTAWESOME).Append(Chr(0xF209)).PopAll
'Using the same builder multiple times. Note that it is initialized each time.
'Note that we vertically align the material icon character.
cs.Initialize.Append("Text with MaterialIcons: ").Typeface(Typeface.MATERIALICONS).VerticalAlign(5dip).Append(Chr(0xE531)).PopAll
Activity.Title = cs
SS-2017-02-15_14.50.53.png


Images

B4X:
Dim cs As CSBuilder
cs.Initialize.Size(30).Typeface(Typeface.MONOSPACE)
cs.Append("B4A: ").Image(LoadBitmap(File.DirAssets, "b4a.png"), 40dip, 40dip, False).Append(CRLF)
cs.Append("B4i: ").Image(LoadBitmap(File.DirAssets, "b4i.png"), 40dip, 40dip, False).Append(CRLF)
cs.Append("B4J: ").Image(LoadBitmap(File.DirAssets, "b4j.png"), 40dip, 40dip, False).Append(CRLF)
cs.Append("B4R: ").Image(LoadBitmap(File.DirAssets, "b4r.png"), 40dip, 40dip, False).Append(CRLF)
cs.PopAll
Label1.Text = cs
Activity.Title = cs
SS-2017-02-15_15.00.33.png


The last parameter sets the image alignment. If it is true then the image will be aligned to the baseline, otherwise it is aligned to the bottom.

Clickable text

The Clickable method creates clickable text. For the event to be raised you must call cs.EnableClickEvents.
The Append method accepts a CharSequence. In the following code the CreateClickableWord sub returns a CharSequence that is then appended to the other CharSqeuence.
B4X:
Sub Activity_Create(FirstTime As Boolean)
   Activity.LoadLayout("1")
   Dim cs As CSBuilder
   cs.Initialize.Size(30).Append("Some ").Append(CreateClickableWord("words"))
   cs.Append(" are ").Append(CreateClickableWord("clickable")).Append(".").PopAll
   Label1.Text = cs
   cs.EnableClickEvents(Label1)
End Sub

Sub CreateClickableWord(Text As String) As CSBuilder
   Dim cs As CSBuilder
   Return cs.Initialize.Underline.Color(0xFF00D0FF).Clickable("word", Text).Append(Text).PopAll
End Sub

Sub Word_Click (Tag As Object)
   Log($"You have clicked on word: ${Tag}"$)
End Sub
SS-2017-02-15_15.33.39.png


ListView also supports CharSequence items

B4X:
For i = 1 To 100
   ListView1.AddSingleLine(cs.Initialize.Color(Rnd(0xFF000000, -1)).Alignment("ALIGN_CENTER").Append($"Item #${i}"$).PopAll)
Next
SS-2017-02-15_15.41.22.png


This allows us to highlight the search term in SearchView:

upload_2017-2-21_17-48-19-png.53072


Center aligned text

B4X:
MsgboxAsync(cs.Initialize.Alignment("ALIGN_CENTER").Append($"Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Nam tristique metus eget sem sollicitudin, vel pulvinar nisl interdum. In sed ullamcorper lacus.
Duis ultricies urna eget faucibus ullamcorper. Donec maximus egestas tortor, vitae suscipit est varius in
Donec at arcu ut odio hendrerit molestie. Curabitur molestie felis enim, ac sodales sapien posuere sit amet."$).PopAll, _
cs.Initialize.Typeface(Typeface.FONTAWESOME).Color(0xFF01FF20).Size(40).Append(Chr(0xF17B) & " " & Chr(0xF17B) & " "& Chr(0xF17B)).PopAll)

SS-2017-02-15_15.51.00.png
 
Last edited:

demasi

Active Member
Licensed User
Longtime User
Is there a method to measure multiine text, like string utils, but for formatted texts?
 

Cebuvi

Active Member
Licensed User
Longtime User
RelativeSize method will be OK

Thanks Erel.
 
Last edited:

demasi

Active Member
Licensed User
Longtime User
Maybe it's a good idea add to csbuilder a method to iniatilize from token marked texts, just like agraham's richtext ibrary:
B4X:
cs.initialize2("This is a {Red}RED{Red} word and this is {B}Bold{B}")
or something like this, from plain text to CS.
I have lots of "token encoded" full texts and applications that will be hard to convert to csbuilder.
 

netsistemas

Active Member
Licensed User
Longtime User
Erel, eres un máquina!!.
Erel, you are a machine!!
Perfect.
 

demasi

Active Member
Licensed User
Longtime User
Thank you, Erel.
I know, I will. But your new method is easier and better.
Sure we need a method to load a long text, already formatted and saved as txt.
I use a B4J program to encode my students lessons texts, and load already formatted to my app in assets folder. it's fast and easy.
And I still can load formatted texts from a server via webservice.
I'm trying to create a function to convert my "token encoded" texts to the new format.
But it's a lot of string manipulation. Ad I still don't know how to load from pre-formatted texts.
Please consider the idea. I'm sure it will help many others.
 

sunish

Member
Licensed User
Longtime User
Is there any memory over head in calling multiple cs.initialize as in cs.Initialize.Append for each append ?
 

luke2012

Well-Known Member
Licensed User
Longtime User
Hi Erel. First of all my compliments :)
Which is the code to append a "smile" icon to a cs that contains some text ?
 

asales

Expert
Licensed User
Longtime User
Hi Erel. First of all my compliments :)
Which is the code to append a "smile" icon to a cs that contains some text ?
B4X:
Chr(0xF118)
open the icon picker (last item in the context menu) and filter field = "smile"
 

DonManfred

Expert
Licensed User
Longtime User
Which is the code to append a "smile" icon to a cs that contains some text ?
B4X:
    Dim obj As CSBuilder
    obj.Initialize.Color(Colors.Red).Append("Hello ").Pop.Append("World!").PopAll
    Religion.Text = cs.Initialize.Append(obj).Append("FontAwesome: ").Typeface(Typeface.FONTAWESOME).Color(Colors.Blue).Append(Chr(0xF209)).PopAll

cs is a global CSBuilder...
 

luke2012

Well-Known Member
Licensed User
Longtime User
@asales & @DonManfred thanks for your help ;-)
I tryed it and it's works!

Only a doubt. How to get the code of the selected icon from the Designer picker ?
 

LucaMs

Expert
Licensed User
Longtime User
Images
B4X:
Dim cs As CSBuilder
cs.Initialize.Size(30).Typeface(Typeface.MONOSPACE)
cs.Append("B4A: ").Image(LoadBitmap(File.DirAssets, "b4a.png"), 40dip, 40dip, False).Append(CRLF)
cs.Append("B4i: ").Image(LoadBitmap(File.DirAssets, "b4i.png"), 40dip, 40dip, False).Append(CRLF)
cs.Append("B4J: ").Image(LoadBitmap(File.DirAssets, "b4j.png"), 40dip, 40dip, False).Append(CRLF)
cs.Append("B4R: ").Image(LoadBitmap(File.DirAssets, "b4r.png"), 40dip, 40dip, False).Append(CRLF)
cs.PopAll
Label1.Text = cs
Activity.Title = cs

Can you use that code for an EditText and delete the images as they were simple single characters?
 

LucaMs

Expert
Licensed User
Longtime User
Hi Luca. I dont understand what you mean. Can you do a little example ?
I mean like many chats, like Whatsapp: you can write normal character, insert an emoticon but also delete it, like any other character; also, it seems to me that Erel used images as if they were emoticons, so...!

Capperi, riesco a spiegarmi meglio in italiano, penso :D.

Volevo sapere se usando questo nuovo "strumento" fosse possibile inserire immagini in una EditText come fossero emoticon e quindi eventualmente cancellarle con il tasto back come qualsiasi altro carattere.
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
Can you use that code for an EditText and delete the images as they were simple single characters?
It will probably be simpler to find a font that includes all the emojis that you like and use it.

You can assign a CharSequence to EditText. I'm not sure how it will work with the images.
 
Status
Not open for further replies.
Top