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: 1,639
Last edited by a moderator:

Kamac

Active Member
Licensed User
Well,

rs.Initialize("This is not a RichString")
rs.Color(Colors.Red, 14, 18)

is actually hard to perform, because we have to count our letters to place the colored word. It takes time, and is very hard to do with dynamic text.


This solution:


rs.Initialize("This is not a $Rich$String")
rs.Color("$", Colors.Red, 14, 18)

would be way better, almost the same as:

rs.Initialize("This is not a <color 0xffff0000>Rich</color>String")
rs.Color(Colors.Red, 14, 18)
 

margret

Well-Known Member
Licensed User
Rich text

First stab at producing rich text strings that support formatting individual characters. The help is presently limited but using this should be pretty obvious.

At the moment the placing of formatting is controlled by start and end indices in the same manner as the normal String methods.

rs.Initialize("This is not a RichString")
rs.Color(Colors.Red, 14, 18)


I am pondering whether it would be useful to either be able to use specified characters or character sequences to indicate format positions.

rs.Initialize("This is not a $Rich$String")
rs.Color("$", Colors.Red, 14, 18)


or do an XML type thing

rs.Initialize("This is not a <color 0xffff0000>Rich</color>String")
rs.Color(Colors.Red, 14, 18)


What are your thoughts?

Hello, What about doing something like this as an idea:

rs.Initialize("This is not a RichString")
rs.Color(Colors.Red, "Rich", "String")


Do the equivalent to At(String) As INT, this way you don't have to count, it will be the same as: rs.Color(Colors.Red, 14, 18). Just a thought.

Thanks,

Margret
 

agraham

Expert
Licensed User
I like the XML/Html variant. I suggest to make the syntax as short as possible (<b>, <u>).
You could do something like that anyway with

rs.Initialize("This <u>is<u> not a RichString")
rs.Underscore2("<u>")

Which I implemented now anyway as it was dead easy. The real decision is to whether to stick to

rs.Initialize("This {R}is{R} not a {R}Rich{R}String")
rs.Color2(Colors.Red, "{R}")

or also implement

rs.Initialize("This <col 0xffff0000>is</col> not a <col 0xffff0000>Rich</col>String")
rs.Color2(Colors.Red, "{R}")

Which gets into XML parsing territory and is also possibly not as easy to use programmatically on dynamic strings. Thoughts?
 

ZJP

Active Member
Licensed User
B4X:
rs.Initialize("This is not a RichString")
rs.Color(Colors.Red, 14, 18)

+1

Edit : Tested. I like this lib. Thx. ;)
 
Last edited:

moster67

Expert
Licensed User
Very nice Agraham. :sign0098:

For labels, it is perfect since mostly the text remains "static" and the text is populated by code.

Just for the fun of it, I tried it also in an EditText-view and the richtext-formatting works nicely there as well. It just gets tricky when you let the user insert and modify text but perhaps using the events of EditText, maybe one can come up with a solution. I will play with it later again and see if I can make a small notepad-application with Richtext-properties.

As always, thanks for your great work.
 

agraham

Expert
Licensed User
Version 1.2 now posted includes the RichStringFormatter object. I'm quite pleased with this.

RichStringFormatter lets you define your formatting tokens once and you can then use it time and time again to format RichStrings by just passing a RichString to it. This should make it much easier to program RichStrings whose formatting may be dynamically changed at runtime.
 

agraham

Expert
Licensed User
Version 1.3 now posted has a couple of improvements.

Previously if you used an undefined token in the RichString passed to a RichStringFormatter your application would force close because the exception was raised on the rendering thread and not the main thread so it could not be caught. Now an explicit check is made for this and a new UnimplementedToken method will return an array of any such encountered while formatting.

A new format option, ScaleX, has been added as I overlooked it before. It expands or compresses text horizontally.
 
Last edited:

corwin42

Expert
Licensed User
I tried to use RichString formatting in a homescreen widget label but it does not work.

Am I right that it is because RemoteView.SetText() has a String type as second parameter so if I pass a RichString it will be converted to a normal String?

I think I currently have no chance to get it working?
 

agraham

Expert
Licensed User
The String type of the Text parameter will indeed be the problem. The underlying Android setTextViewText method does in fact take a CharacterSequence type so it could probably be made to work with the Reflection library. If you post a small project with a widget with a label showing your present attempt I'll see if I can modify it to work.
 

corwin42

Expert
Licensed User
Thanks very much, but...

B4X:
Compiling code.                         Error
Error compiling program.
Error description: Too many parameters.
Occurred on line: 40
args(1) = rsf.Format(rs, rsf.SPAN_INCLUSIVE_EXCLUSIVE) ' CharSequence
Word: rsf

New version of RichString Library?
 
Top