B4A Library LabelExtras - advanced click handling

LabelExtras enables you to apply click listeners to sub-strings of a Label text.
A click on a sub-string raises an event and you can take whatever action you desire on such a click.

LabelExtras also exposes the Android Html class so you can use basic HTML formatting elements such as <b>, <i> and <u> in your Label text.

Here's the library reference:

LabelExtras
Version:
1.12
  • ClickableSpan
    Events:
    • Click (SelectionStart As Int, SelectionEnd As Int)
    • Click2 (SelectionStart As Int, SelectionEnd As Int, Tag As Object)
    Methods:
    • Initialize (EventName As String, Color As Int, UnderlineText As Boolean)
      Initialize the ClickableSpan.
      Color defines the color of the clickable text, pass -1 if you do not wish to change that text color.
      UnderlineText defines whether the clickable text shall be underlined.
      The Click(SelectionStart As Int, SelectionEnd As Int) event will be raised when this ClickableSpan is clicked.
    • Initialize2 (EventName As String, Color As Int, UnderlineText As Boolean, Tag As Object)
      Initialize the ClickableSpan.
      Color defines the color of the clickable text, pass -1 if you do not wish to change that text color.
      UnderlineText defines whether the clickable text shall be underlined.
      Pass any Object as the Tag and this Object will be returned to the Click2 event.
      The Click2(SelectionStart As Int, SelectionEnd As Int, Tag As Object) event will be raised when this ClickableSpan is clicked.
    • IsInitialized As Boolean
  • Html
    Events:
    • GetDrawable (Source As String) As Object
    • HandleTag (Opening As Boolean, Tag As String, SpannableStringBuilder1 As SpannableStringBuilder)
    Methods:
    • EscapeHtml (CharSequence1 As CharSequence) As String
      Returns an HTML escaped representation of the given plain text.
      Only available with Android AP version 16+.
    • FromHtml (HtmlString As String) As CharSequence
      Returns displayable styled text from the provided HTML string.
    • FromHtml2 (HtmlString As String, ImageGetterEventName As String, TagHandlerEventName As String) As CharSequence
      Returns displayable styled text from the provided HTML string.
      Using optional ImageGetter (to handle HTML IMG tags in the String) and TagHandler (to handle unrecognised tags in the String) callbacks.
      The drawable returned by the ImageGetter sub has to be sized with setBounds.
    • ToHtml (CharSequence1 As CharSequence) As CharSequence
      Returns an HTML representation of the provided Spanned text.
  • LabelExtras
    Methods:
    • SetDrawableBounds (Drawable1 As Drawable, Left As Int, Top As Int, Right As Int, Bottom As Int)
      Specifies a bounding rectangle for the drawable.
      Required for the Html Object ImageGetter callback.
    • SetMovementMethod (Label1 As TextView, MovementMethod1 As MovementMethod)
      Sets the movement method (arrow key handler) to be used for this TextView.
      To enable the LabelExtras click functionality you must set your Label movement method to an instance of LinkMovementMethod.
      The LinkMovementMethod.GetInstance method returns the instance required.
  • LinkMovementMethod
    Methods:
    • GetInstance As MovementMethod
      Returns an instance of the LinkMovementMethod which is required by the LabelExtras.SetMovementMethod method.
  • SpannableStringBuilder
    Methods:
    • Append (Text As CharSequence) As SpannableStringBuilder
    • Append2 (Text As CharSequence, Start As Int, End As Int) As SpannableStringBuilder
    • Append3 (Char1 As Char) As SpannableStringBuilder
    • CharAt (Where As Int) As Char
    • Clear
    • ClearSpans
    • Delete (Start As Int, End As Int) As SpannableStringBuilder
    • GetChars (Start As Int, End As Int, Dest() As Char, DestOffset As Int)
    • GetSpanEnd (Span1 As Object) As Int
    • GetSpanFlags (Span1 As Object) As Int
    • GetSpanStart (Span1 As Object) As Int
    • GetStyleSpans (QueryStart As Int, QueryEnd As Int) As StyleSpan[]
    • GetURLSpans (QueryStart As Int, QueryEnd As Int) As URLSpan[]
    • GetUnderlineSpans (QueryStart As Int, QueryEnd As Int) As UnderlineSpan[]
    • Initialize (CharSequence1 As CharSequence)
      Initialize the SpannableStringBuilder with a CharSequence.
      A CharSequence can be obtained using the Html.FromHtml method, a String can also be passed as a CharacterSequence.
    • IsInitialized As Boolean
    • NextStyleSpanTransition (Start As Int, Limit As Int) As Int
      Return the next offset after Start but less than or equal to Limit where a StyleSpan begins or ends.
    • NextURLSpanTransition (Start As Int, Limit As Int) As Int
      Return the next offset after Start but less than or equal to Limit where a URLSpan begins or ends.
    • NextUnderlineSpanTransition (Start As Int, Limit As Int) As Int
      Return the next offset after Start but less than or equal to Limit where an UnderlineSpan begins or ends.
    • RemoveSpan (Span1 As Object)
    • Replace (Start As Int, End As Int, CharSequence1 As CharSequence) As SpannableStringBuilder
    • Replace2 (Start As Int, End As Int, CharSequence1 As CharSequence, CharSequence1Start As Int, CharSequence1End As Int) As SpannableStringBuilder
    • SetSpan (Span1 As Object, Start As Int, End As Int, Flags As Int)
    Properties:
    • Length As Int [read only]
      Return the number of Chars in the buffer.
  • Spanned
    Fields:
    • SPAN_EXCLUSIVE_EXCLUSIVE As Int
      Constant which can be passed as the SpannableStringBuilder.SetSpan method Flags parameter.
      Spans of type SPAN_EXCLUSIVE_EXCLUSIVE do not expand to include text inserted at either their starting or ending point.
    • SPAN_EXCLUSIVE_INCLUSIVE As Int
      Constant which can be passed as the SpannableStringBuilder.SetSpan method Flags parameter.
      Non-0-length spans of type SPAN_EXCLUSIVE_INCLUSIVE expand to include text inserted at their ending point but not at their starting point.
    • SPAN_INCLUSIVE_EXCLUSIVE As Int
      Constant which can be passed as the SpannableStringBuilder.SetSpan method Flags parameter.
      Non-0-length spans of type SPAN_INCLUSIVE_EXCLUSIVE expand to include text inserted at their starting point but not at their ending point.
    • SPAN_INCLUSIVE_INCLUSIVE As Int
      Constant which can be passed as the SpannableStringBuilder.SetSpan method Flags parameter.
      Spans of type SPAN_INCLUSIVE_INCLUSIVE expand to include text inserted at either their starting or ending point.
  • StyleSpan
    Methods:
    • GetStyle As Int
      Returns the Typeface style of this StyleSpan.
      Typeface.STYLE_BOLD, Typeface.STYLE_ITALIC etc.
    • IsInitialized As Boolean
  • URLSpan
    Methods:
    • GetURL As String
    • IsInitialized As Boolean
  • UnderlineSpan
    Methods:
    • IsInitialized As Boolean

Example code to follow.

Martin.
 

Attachments

  • LabelExtras_v1_12.zip
    15.9 KB · Views: 1,951
Last edited:

urikupfer

Member
Licensed User
Longtime User
Hi Martin
Thanks for the answer , I am using the function "fromHtml(html string)" , just to convert the html string to text , something like reach text,
but from the link you gave me I saw the answer :" This class processes HTML strings into displayable styled text. Not all HTML tags are supported."
Uri
 

android6dft

New Member
Licensed User
Longtime User
Code as Sub

Take a look at the code I mixed the latest versions of AHViewPager, Scrollview and LabelExtras but it seems a lag in parsing or displaying the page contains html codes. Add more html codes and images to it to see the amplified effect.
Can you please check and guide in this issue? I only want the text formatting not required link/click identification. Attached the full project folder.
Thanks.

Full project files: https://www.dropbox.com/s/hud71asx02qcl2t/WORKING.zip
 
Last edited:

warwound

Expert
Licensed User
Longtime User
How to manage ClickableSpan in case of more than one label?

Have you read post #35 and #37 in this thread?

You can use the ClickableSpan Initialize2 method and listen for the Click2 event - this enables you to assign any object/value to each ClickableSpan as it's Tag.
So assign a unique Tag to each ClickableSpan and in the Click2 event use the Tag to establish which ClickableSpan was clicked.

Martin.
 

ferya

Member
Licensed User
Longtime User
Sorry but I have another problem
I cant use eastern language characters,I changed your text as bellow but it dos not do anything.
Also I checked it in html method.
B4X:
    SpannableStringBuilder1.Initialize("این یک آزمایش است")' plain String."&CRLF&"It contains no HTML tags and has NOT been passed to the Html.FromHtml method."&CRLF&"A click listener will be added to the word 'plain' in the first sentence.")
    Dim ClickableSpan1 As ClickableSpan
    ClickableSpan1.Initialize("ClickableSpan1", Colors.Magenta, True)
    SpannableStringBuilder1.SetSpan(ClickableSpan1, 8, 14, Spanned1.SPAN_EXCLUSIVE_EXCLUSIVE)
thank you in advance
 

warwound

Expert
Licensed User
Longtime User
What do you mean by 'it does not do anything'?

Do these foreign characters display on the android device but they are not clickable?
Or do these characters simply fail to display?

If you take a Label and set the Label text to these characters do you see them correctly displayed?

Martin.
 

ferya

Member
Licensed User
Longtime User
Hi,
They displayed well but they are not clickable.
Also the color has changed.
 

warwound

Expert
Licensed User
Longtime User
Can you put together a small n simple test project - and upload it.
I'll take a look and see what i establish is not working correctly.

Martin.
 

ferya

Member
Licensed User
Longtime User
Please see the attached.
consider I have a commented line that started whit "A" key if you uncomment it program works.
B4X:
's="Aکارگه <b>سلام</b> <b>خوبی</b> چه خبر "&CRLF
but in my label whole chars must be other language.
thank you Martin.
 

Attachments

  • demobold.zip
    3.8 KB · Views: 276

warwound

Expert
Licensed User
Longtime User
Hmmm...

I tried your project on my old ZTE Blade that's running CyanogenMod Gingerbread 2.3 and it worked as expected.
I then added an asterix between the two bold spans of text and again it worked as expected, each bold span of text raising the correct ClickableSpan Click event (see attached demobold_labelextras_blade.png).
Note that the text is correctly aligned as 'right to left' text.

Next i tried your project on my Galaxy Tab2 running Jelly Bean 4.1.1, the text is aligned as 'left to right' text and no clicks are detected (see attached demobold_labelextras_tab2.png).

Appending the character A to the string caused the bold spans to be clickable but they were still displayed as 'left to right' text.
Appending a space (instead of an A) to the string caused the bold spans to be not clickable.

I then tried surrounding your text in an HTML SPAN element:

B4X:
s="<span>کارگه <b>سلام</b> * <b>خوبی</b> چه خبر </span>"&CRLF

The bold spans were no longer clickable.
Using an HTML P element was the same - the bold spans were not clickable.

I tried adding a new method to the Html object:

B4X:
   /**
    * Returns displayable styled text from the provided HTML string specifying the character encoding of the string.
    */
   public static CharSequence FromHtml3(String HtmlString, String Encoding) throws UnsupportedEncodingException {
     return android.text.Html.fromHtml(new String(HtmlString.getBytes(), Encoding));
   }

And updating the b4a code to use this new method:

B4X:
   Dim s As String
   s="کارگه <b>سلام</b> * <b>خوبی</b> چه خبر "&CRLF

   '   s="Aکارگه <b>سلام</b> * <b>خوبی</b> چه خبر "&CRLF

   Dim HtmlString As String=s


   SpannableStringBuilder1.Initialize(Html1.FromHtml3(HtmlString, "UTF-8"))

This made no difference, the results were exactly as before.

Finally i tried appending the character A to the string and then removing it from the SpannableStringBuilder:

B4X:
s="Aکارگه <b>سلام</b> * <b>خوبی</b> چه خبر "&CRLF
Dim HtmlString As String=s
SpannableStringBuilder1.Initialize(Html1.FromHtml(HtmlString))
SpannableStringBuilder1.Delete(0, 1)

The A is removed but now the bold spans are no longer clickable.

So the problem is likely to be device specific and (more accurately) android version specific i think.
It works perfectly on Gingerbread 2.3, the text is displayed as right to left text and the bold spans are clickable.
On Jelly Bean the only way that i could make the bold spans clickable was to display a single english character (A) with the foreign text.

I'm not sure what to suggest next :(.

Martin.
 

Attachments

  • demobold_labelextras_blade.png
    demobold_labelextras_blade.png
    58.8 KB · Views: 313
  • demobold_labelextras_tab2.png
    demobold_labelextras_tab2.png
    12.4 KB · Views: 298

ferya

Member
Licensed User
Longtime User
Hi,
Really hanks for your try.
I tested on galaxytab2 and note2.
please inform me if you could find a way.
best regards
 

ferya

Member
Licensed User
Longtime User
Hi Martin
I checked program with Hebrew characters and it has same problem.
 

Attachments

  • demoboldHebrew.zip
    3.8 KB · Views: 292

warwound

Expert
Licensed User
Longtime User
Hi again.

I just tried the Hebrew example on an unbranded 5" chinese tablet running ICS 4.0.4 and it worked.

So i tried the previous example (demobold.zip) on the same tablet - it didn't work.

Next i started a Froyo (2.2) emulator and would you believe BOTH example projects work perfectly.
The text displays as left to right, not right to left so maybe not perfect - but the clickable spans do raise the click event.

I'd guess that support for these languages is entirely dependant on the firmware of the device.
Some firmware has support for these languages and some doesn't.
BUT that doesn't explain how the actual text is displayed using the correct font yet the clickable spans do not raise a click event.

I'm not sure what to suggest next :(.

Martin.
 

warwound

Expert
Licensed User
Longtime User
Well there is no official list of HTML tags that are supported.

There's an old article here that documents supported tags: http://commonsware.com/blog/Android/2010/05/26/html-tags-supported-by-textview.html
But that's dated May 2010!.

The general view is to look at the android source code for the HTML class - look at the version that's relevant for your application - and see if you can work out what tags are currently supported.

Nowhere do i see marquee listed as a supported tag, you could try it and see if it works but it seems likely that it won't work.

Martin.
 

M.LAZ

Active Member
Licensed User
Longtime User
Well there is no official list of HTML tags that are supported.

There's an old article here that documents supported tags: http://commonsware.com/blog/Android/2010/05/26/html-tags-supported-by-textview.html
But that's dated May 2010!.

The general view is to look at the android source code for the HTML class - look at the version that's relevant for your application - and see if you can work out what tags are currently supported.

Nowhere do i see marquee listed as a supported tag, you could try it and see if it works but it seems likely that it won't work.

Martin.


thanks
yes i found a marquee label in the forum ...
here
http://www.b4x.com/android/forum/threads/scrolling-labels.8831/#post-198540
in two directions right to left - and left to right
thanks to Klaus
Right to left Marquee Label
http://www.b4x.com/android/forum/attachments/scrollinglabels-zip.20150/
 

coslad

Well-Known Member
Licensed User
Longtime User
It works

Hi Martin,
Thank your new library.It is enough to make it work.see the code:
B4X:
Sub Button1_Click
   Dim str As String
   sp.Clear
   str = html1.CharSequenceFromEditTextToHtml(EditText1)
   Dim matcher1 As Matcher
   matcher1 = Regex.Matcher("<(?!br|img)[^>]+>",str)
   Do While matcher1.Find
      str = str.Replace(matcher1.Match,"")
   Loop
   Log("[Button1_Click]str="&str)
   'sp.Append(html1.CharSequenceFromEditTextToHtml(EditText1))
   sp.Append(html1.FromHtml2(str&"<img src='1.gif' />","ImageGetter",""))
   EditText1.Text = sp
   EditText1.SelectionStart = EditText1.Text.Length
   Log("[Button1_Click]text="&EditText1.Text)
End Sub
i just append the string from html1.CharSequenceFromEditTextToHtml(EditText1) to the new input string,and parse the whole string to html again.maybe it seems to be low efficient to pare the whole string every time,but it works at least.
thank you.

hi, i tried your code and it works , but i can't find a way to save the edit text with the image and read it back,i thought to usa same place holder, can you help me? many thanks

Correct me , i can save with this code :

B4X:
str = html1.CharSequenceFromEditTextToHtml(EditText1)
File.WriteString(File.DirRootExternal,"html.txt",str)

But i can't read it , plaese help me ! Thanks
 
Last edited:

coslad

Well-Known Member
Licensed User
Longtime User
HI

i solved with this code :

B4X:
appoggio=File.ReadString(File.DirRootExternal,"html.txt")
sp.Initialize(html1.FromHtml2(appoggio, "ImageGetter", "TagHandler"))
EditText1.Text=sp
 

Juan Pablo da Rocha

Member
Licensed User
Longtime User
Hi! Thanks for this library, it's very useful.

I could use some simple HTML tags and Works fine. Is it possible to use "Font size"?

Thanks in advance
Juan Pablo
 
Top