Sunday, April 1, 2012

Rich TextView

When we want to have beauty and stylish text we call html for help. According to Formatting and Styling document there are only 3 supported tags: b, i, and u. It also contains some mentions about fromHtml method, but it doesn't nearly cover some of the useful cases.
Let's taking closer to implementation. Containing not just CharSequence, but being able to convert this buffer to SpannableString (in setText method) TextView became powerful markup container (since SpannableString implements Spannable - interface for text whith markup objects). As for possible markup values within your string resources: in the depths of AssetManager we can see, that array of StringBlock is used to retrieve data from compiled string resources and return them via getString method. So, after considering applyStyles we can list supported tags:
  • <a href="">(supports attributes "href")
  • <annotation>
  • <b>
  • <big>
  • <font> (be aware, use "fgcolor" attribute instead "color")
  • <i>
  • <li>
  • <marquee>
  • <small>
  • <strike>
  • <sub>
  • <sup>
  • <tt>
  • <u>
  • <ul>

Html#fromHtml gives us even more. It uses HtmlToSpannedConverter, which supports:
  • <a href="">(supports attributes "href")
  • <b>
  • <big>
  • <blockquote>
  • <br>
  • <cite>
  • <dfn>
  • <div>
  • <em>
  • <font>(supports attributes "color" and "face")
  • <i>
  • <img>
  • <p>
  • <small>
  • <strong>
  • <sub>
  • <sup>
  • <tt>
  • <u>

Let's take a look to example. Here is strings.xml:
 <?xml version="1.0" encoding="utf-8"?>  
 <resources>  
   <string name="simple_raw_string">I\'m simple raw string</string>  
   <string name="html_string_1">  
     <font bgcolor='#ff440050'><b>I\'m</b> <i>html</i> <font fgcolor='#ffff5400'>string</font></font>  
   </string>  
   <string name="html_string_2"><![CDATA[  
     <em>I\'m</em> <font color=\'#0054ff\'>another</font> <br> <dfn>html</dfn> <big>string</big>]]>  
   </string>  
 </resources>  

Layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent">

    <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="@string/simple_raw_string"/>

    <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="@string/html_string_1"/>

    <TextView
            android:id="@+id/html_text"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"/>


</LinearLayout>
And main activity
   @Override  
   public void onCreate(Bundle savedInstanceState) {  
     super.onCreate(savedInstanceState);  
     setContentView(R.layout.layout);  
     ((TextView) findViewById(R.id.html_text)).setText(Html.fromHtml(getString(R.string.html_string_2)));  
   }  
And how it looks on device

2 comments:

  1. Hi Vlad i have tried setting font color as you did but its not working??can you please help

    ReplyDelete
  2. Hi Raja,

    in example above background color was set up by 2 different approaches:
    1) with tag 'font' and attribute 'fgcolor'; and this string resource is assigned through xml layout
    2) with tag 'font' and attribute 'gcolor'; and this string is assigned programmatically, using 'Html.fromHtml' method.

    which approach are you trying to use? be aware, that this is important to wrap your string resources in 'CDATA' brackets (as i did for 'html_string_2') if you want to 'Html.fromHtml' reads it correctly.

    ReplyDelete