B4A Library RichString library.

This library contains RichString and RichStringBuilder objects. These objects are analogous to the normal String and StringBuilder. However RichStrings can contain formatting information that controls how they are drawn when used as the text in a View.

This library also contains a RichStringFormatter object. This object, once suitably initialised, will efficiently format RichStrings passed to it. For long strings that require many changes of format this is much more efficient than using the individual RichString formatting commands.


EDIT :- Version 1.1 posted. See post #8 for details.

EDIT :- Version 1.2 posted including RichStringFormatter. See post #13 for details.

EDIT :- Version 1.3 posted. See post #15 for details.

EDIT :- Version 1.4 posted. See post #56 for details.

EDIT (by Erel) :- Version 1.5: https://www.b4x.com/android/forum/threads/richstring-library.10680/page-6#post-475477
 

Attachments

  • RichString.zip
    11.6 KB · Views: 2,499
Last edited by a moderator:

noclass1980

Active Member
Licensed User
Longtime User
Sorry not to be clearer. What I meant was that the text file which is loaded into the scrollview contains the formatting codes e.g. {U} around some text which then appears underlined in the scrollview. So as I write the plain text I can include the formatting codes for underline, bold, colours etc and, as long as these codes are intialised correctly, then then plain text is formatted in the scrollview.
e.g. the "RTF Example.txt" text file contains the following lines

{U}This is the Title{U}

{Red}the following text is now red{Red}{Blue}and now it is blue{Blue}

would the code for loading the "RTF Example.txt" into label1 look something like:
B4X:
Dim rsf As RichStringFormatter
Dim txt as String
txt=File.GetText(File.DirAssets, "RTF Example.txt")
rsf.AddToken("{Blue}", rsf.FORMAT_COLOR, Colors.Blue)
rsf.AddToken("{Red}", rsf.FORMAT_COLOR, Colors.Red)
rsf.AddToken("{U}", rsf.FORMAT_UNDERSCORE, Null)
rs.initialise(txt)
rs=rsf.Format(rs)
label1.txt=rs

Hope this makes more sense. I remember using software called Tasword (on an Einstein computer) about 27 years ago that used the same approach with the formatting codes.
 
Last edited:

agraham

Expert
Licensed User
Longtime User
You need to look at the RichString demo to see how it works but basically you Initialise a RichString with your plaintext, format the RichString with a RichStringFormatter and assign the RichString to the Text property of an AutoCompleteEditText, EditText, Button or Label. That code looks about right, - why not just go ahead and try it!
 

noclass1980

Active Member
Licensed User
Longtime User
Because I'm at work and can't have the Galaxy tab out on the desk!
:)
 

noclass1980

Active Member
Licensed User
Longtime User
Adding to RichString library

Hi, thanks for the help, I've tried the code and it works nicely (see attached). I'm niot familiar with Libraries (yet!). How do I change the library so that a bullet (or some other ASCII symbol) could be included as a token? thanks
 

Attachments

  • RichTextExample.zip
    7.6 KB · Views: 373

agraham

Expert
Licensed User
Longtime User
How do I change the library so that a bullet (or some other ASCII symbol) could be included as a token? thanks
I'm not sure what you mean by this. Libraries are written in Java and then compiled so you need a Java IDE and the library source to change it.

What do you mean by "including ASCII symbols (strictly UTF16 codepoints) as a token"? If you want a bullet or some other odd character find its UTF16 codepoint value and append it to a string using Chr().

The full range of formats and styles that a Java SpannableString, which is what a RichString is, supports are already available.
 

mjtaryan

Active Member
Licensed User
Longtime User
Hi, thanks for the help, I've tried the code and it works nicely (see attached). I'm niot familiar with Libraries (yet!). How do I change the library so that a bullet (or some other ASCII symbol) could be included as a token? thanks

I have a folder called "Snippets" in which I store snatches of code. One of those snippets is the section in the RichString library demo that initializes the formatter and defines some of the tokens. I can then copy the code and paste it into my project and then modify it (change token defintions, add tokens, remove tokens, etc. You might find doing something similar to be useful if you plan on using a significant amount of rich text in your projects (lwhether across projects or in a single one). Just a thought.
 

b4AMarkO

Member
Licensed User
Longtime User
Trying to get my head around this

Why is this not working?

B4X:
Dim rs As RichString   
   Dim now As Long
    now = DateTime.now 
   DateTime.Timeformat="HH:mm"
    Dim myEt As String
    Dim myTime As String
    myTime = now
   
    rs.Initialize("{R}{T}{Blue}" & DateTime.Time(myTime) & "{Blue}{T}{R}")
   rs.Color2(Colors.Blue,"{Blue}")
   rs.RelativeSize2(1.5, "{R}")
   rs.Typeface2("serif", "{T}")
   
      
      
   If etLog.Text <> "" Then
      etLog.Text = etLog.Text & CRLF & CRLF & rs & ":  "
      etLog.SelectionStart = etLog.Text.Length & "  "
    Else
       etLog.Text = rs & ":  "
      etLog.SelectionStart = etLog.Text.Length & "  "
    End If
 

b4AMarkO

Member
Licensed User
Longtime User
You should add the text to RichString in the Initialize method. In your code the RichString object will be converted to a regular string.

Yes ..... your right about it converting it to a regular string .....

Not sure why it is

Ok, you said I should add the text to RichString in the Initialize method
Erel please forgive but I'm not following you there ... might you elaborate

:BangHead: Banging my head on this one
 

b4AMarkO

Member
Licensed User
Longtime User
The string concatenation is converting it to a normal string
B4X:
etLog.Text = rs & ":  "
You should do

B4X:
rs.Initialize("{R}{T}{Blue}" & DateTime.Time(myTime) & "{Blue}{T}{R}"  & ":  "

Make sure you understand the examples in the demo.

Ok Ill give that a go but if I understand you this is going to be a problem then

when I add the time stamp for the first time it will work but if I add a 2nd timestamp the formatted text wont be retained but will be converted to regular strings ... right?

IM thinking so but I will test it

'******** Tested it below is code tested with *******************

B4X:
If etLog.Text <> "" Then
      etLog.Text = etLog.Text & CRLF & CRLF & DateTime.Time(myTime) & ":  "
      etLog.SelectionStart = etLog.Text.Length & "  "
    Else
       rs.Initialize("{R}{T}{Blue}" & DateTime.Time(myTime) & ":  {Blue}{T}{R}")
      rs.Color2(Colors.Blue,"{Blue}")
      rs.RelativeSize2(1.5, "{R}")
      rs.Typeface2("serif", "{T}")
      etLog.Text = rs
      etLog.SelectionStart = etLog.Text.Length & "  "
    End If

NOTE: after the Else code works great ..... but I havent a clue how to write it before the else to keep the text that is already formatted in the textbox ... unless I over looked that ...

sorry for being such a bother I am trying to understand how this works
 
Last edited:

b4AMarkO

Member
Licensed User
Longtime User
From the help in the xml for the RichString library



Im not yet getting it I guess ...
Here is what I am doing
I did look over the help read again what you quoted from it

Using the Append I think... possibly I am heading the right way but still
I am converting the already formatted text within etLog.Text back to a regular string

here is my code

B4X:
If etLog.Text <> "" Then
      rs.Initialize("{R}{T}{Blue}" & DateTime.Time(myTime) & ":  {Blue}{T}{R}")
      rs.Color2(Colors.Blue,"{Blue}")
      rs.RelativeSize2(1.5, "{R}")
      rs.Typeface2("serif", "{T}")
      rsb.Initialize 
      rsb.Append(etLog.Text & CRLF & CRLF)' Coverting back to regular string
                                          ' How do I avoid this?
      rsb.Append(rs)
      
       etLog.Text = rsb
       etLog.SelectionStart = etLog.Text.Length & "  "
    Else
       rs.Initialize("{R}{T}{Blue}" & DateTime.Time(myTime) & ":  {Blue}{T}{R}")
       rs.Color2(Colors.Blue,"{Blue}")
       rs.RelativeSize2(1.5, "{R}")
       rs.Typeface2("serif", "{T}")
       etLog.Text = rs
       etLog.SelectionStart = etLog.Text.Length & "  "
    End If

:confused:
 

mjtaryan

Active Member
Licensed User
Longtime User
Reading this conversation raises a posdible suggestion or solution (I've done this with some of my RichStrings) -- could you not create two RichStrings, say rs1 and rs2. The first would be for the first timestamp and rs2 would be for the second. Then, if you need to concatenate them, you get 'rs1 & ":" & rs2 & "..."

Sorry for adding my 2 cents worth.

Sent from my SAMSUNG-SGH-I317 using Tapatalk 2
 

b4AMarkO

Member
Licensed User
Longtime User
Reading this conversation raises a posdible suggestion or solution (I've done this with some of my RichStrings) -- could you not create two RichStrings, say rs1 and rs2. The first would be for the first timestamp and rs2 would be for the second. Then, if you need to concatenate them, you get 'rs1 & ":" & rs2 & "..."

Sorry for adding my 2 cents worth.

Sent from my SAMSUNG-SGH-I317 using Tapatalk 2



2 Cents is much appreciated .....

Ill give that some thought ..... this thing is kicking my tail .... just to rusty ... my vb and then try adding thinking in B4A where not everything is the same ... not complaining ... this is an awesome software for sure I am determined to learn it

Anyway, that being said ... I am trying to figure out how to take mulitple lines of text and reformat it ... cause I cant figure out another way to grab that text and retain its format ...

I think I am really getting close now
But alas IM iterating through this wrong or something but it looks right to me

B4X:
myArr = Regex.Split(CRLF, etLog.Text)
          For Each line As String In myArr
             If line.Contains(": ") Then
              newArr = Regex.Split("  ", line)
              Dim tStamp As String = newArr(0)
              Dim tsText As String = newArr(1)
               rs.Initialize("{R}{T}{Blue}" & tStamp & "{Blue}{T}{R} " & tsText)
               rs.Color2(Colors.Blue, "{Blue}")
               rs.RelativeSize2(1.5, "{R}")
               rs.Typeface2("serif", "{T}")
                  rsb.Initialize
                rsb.Append(rs)
                etLog.Text = rsb
               Log(line)
            End If   
          Next

I have two lines with text

16:07: Some Text here
16:54: Some more text here

and the Log shows its getting both but when I execute I only see below in EditText

16:54: Some more text here

what is the obvious thing I am missing here
 
Last edited:

mjtaryan

Active Member
Licensed User
Longtime User
2 Cents is much appreciated .....

Ill give that some thought ..... this thing is kicking my tail .... just to rusty ... my vb and then try adding thinking in B4A where not everything is the same ... not complaining ... this is an awesome software for sure I am determined to learn it

Anyway, that being said ... I am trying to figure out how to take mulitple lines of text and reformat it ... cause I cant figure out another way to grab that text and retain its format ...

I think I am really getting close now
But alas IM iterating through this wrong or something but it looks right to me

B4X:
myArr = Regex.Split(CRLF, etLog.Text)
          For Each line As String In myArr
             If line.Contains(": ") Then
              newArr = Regex.Split("  ", line)
              Dim tStamp As String = newArr(0)
              Dim tsText As String = newArr(1)
               rs.Initialize("{R}{T}{Blue}" & tStamp & "{Blue}{T}{R} " & tsText)
               rs.Color2(Colors.Blue, "{Blue}")
               rs.RelativeSize2(1.5, "{R}")
               rs.Typeface2("serif", "{T}")
                  rsb.Initialize
                rsb.Append(rs)
                etLog.Text = rsb
               Log(line)
            End If   
          Next

I have two lines with text

16:07: Some Text here
16:54: Some more text here

and the Log shows its getting both but when I execute I only see below in EditText

16:54: Some more text here

what is the obvious thing I am missing here

I'very come into this late, but I gather you are trying to construct a log. Does this log have more than two entries (or will It have when you get this working right)? What is the trigger or criteria for the second line? I would suggest you determine what the triggers are for both entries. Then use those to capture the two times in separate variables, format each as needed and concatenate as necessary. It is sometimes easier to keep track of things when separate variables are used. If these are declared in subs there will be minimal overhead and then only While tge sub is running. Additionally, you are getting the second line omly because you seem to be overwriting the variable holding the first line with the second.
 
Last edited:

b4AMarkO

Member
Licensed User
Longtime User
I'very come into this late, but I gather you are trying to construct a log. Does this log have more than two entries (or will It have when you get this working right)? What is the trigger or criteria for the second line? I would suggest you determine what the triggers are for both entries. Then use those to capture the two times in separate variables, format each as needed and concatenate as necessary. It is sometimes easier to keep track of things when separate variables are used. If these are declared in subs there will be minimal overhead and then only While tge sub is running. Additionally, you are getting the second line omly because you seem to be overwriting the variable holding the first line with the second.

Does the Log have more than two entries ....
At the moment etLog.Text ( my EditText) has two entries for the purpose of this test .... but it might have 20 or more such entries
Im trying to parse through the EditText ... in this case adding each line of the EditText into an array and iterating the array
Then split the contents of the array into two different strings
Format the Strings in rs.Initialize (ect ect)

Oh as for the triggers I do not know what you mean by that

Overwriting the variable

Might be ... but do you think you might point out how I am doing that and maybe suggest a solution ...

Ive been on this one all day ... my brain hurts and Im about to abandon it for awhile .... maybe forever LOL ... ok not forever .... :)

:sign0163:
 

mjtaryan

Active Member
Licensed User
Longtime User
I have used the RichString library Before, but only with text files in which I have already added the formatting tokens and It worked fine. But I have never done It with shortly trxt to which the tokens are added in the rs(initialize) string. I have assumed, perhaps incorrectly, that you where building the login from start with rach line of the edittext being formatted and added as the result of Someone condition or event (the trigger as I call It) such as a button click. Underlying this assumption, since I had some time, I spent the day putting together a quick and dirty program hoping to find a resolution to your dillima. Alas, in spite of having used RichString successfully Before, I am running into the same problem you are (plus a couple of additional but unrelated ones).

To try to trace the difficulty I've inserted several login statements in appropriate places and have discovered that after It is initialized, "rs" contains the original text bookended by the formatting tokens I've used. However, the formatter returns a string that has been stripped of the tokens. I will try another approach tomorrow.

Sorry.
 
Top