The following is the first few sections of a chapter from The Busy Coder's Guide to Android Development, plus headings for the remaining major sections, to give you an idea about the content of the chapter.


Rich Text

Plain text is so, well, plain.

Fortunately, Android has fairly extensive support for formatted text, before you need to break out something as heavy-weight as WebView. However, some of this rich text support has been shrouded in mystery, particularly how you would allow users to edit formatted text.

This chapter will explain how the rich text support in Android works and how you can take advantage of it, with particular emphasis on some open source projects to help you do just that.

Prerequisites

Understanding this chapter requires that you have read the core chapters, particularly the ones on basic widgets and the input method framework.

The Span Concept

You may have noticed that many methods in Android accept or return a CharSequence. The CharSequence interface is little used in traditional Java, if for no other reason than there are relatively few implementations of it outside of String. However, in Android, CharSequence becomes much more important, because of a sub-interface named Spanned.

Spanned defines sequences of characters (CharSequence) that contain inline markup rules. These rules — mostly instances of CharacterStyle and ParagraphStyle subclasses – indicate whether the “spanned” portion of the characters should be rendered in an alternate font, or be turned into a hyperlink, or have other effects applied to them.

Methods that take a CharSequence as a parameter, therefore, can work equally well with String objects as well as objects that implement Spanned.

Implementations

The base interface for rich-text CharSequence objects is Spanned. This is used for any CharSequence that has inline markup rules, and it defines methods for retrieving markup rules applied to portions of the underlying text.

The primary concrete implementation of Spanned is SpannedString. SpannedString, like String, is immutable — you cannot change either the text or the formatting of a SpannedString.

There is also the Spannable sub-interface of Spanned. Spannable is used for any CharSequence with inline markup rules that can be modified, and it defines the methods for modifying the formatting. There is a corresponding SpannableString implementation.

Finally, there is a related Editable interface, which is for a CharSequence that can have its text modified in-place. SpannableStringBuilder implements both Editable and Spannable, for modifying text and formatting at the same time.

TextView and Spanned

One of the most important uses of Spanned objects is with TextView. TextView is capable of rendering a Spanned, complete with all of the specified formatting. So, if you have a Spanned that indicates that the third word should be rendered in italics, TextView will faithfully italicize that word.

TextView, of course, is an ancestor of many other widgets, from EditText to Button to CheckBox. Each of those, therefore, can use and render Spannable objects. The fact that EditText has the ability to render Spanned objects — and even allow them to be edited — is key for allowing users to enter rich text themselves as part of your UI.

Available Spans

As noted above, the markup rules come in the form of instances of base classes known as CharacterStyle and ParagraphStyle. Despite those names, most of the SDK-supplied subclasses of CharacterStyle and ParagraphStyle end in Span (not Style), and so you will likely see references to these as “spans” as often as “styles”. That also helps minimize confusion between character styles and style resources.

There are well over a dozen supplied CharacterStyle subclasses, including:

  1. ForegroundColorSpan and BackgroundColorSpan for coloring text
  2. StyleSpan, TextAppearanceSpan, TypefaceSpan, UnderlineSpan, and StrikethroughSpan for affecting the true “style” of text
  3. AbsoluteSizeSpan, RelativeSizeSpan, SuperscriptSpan, and SubscriptSpan for affecting the size (and, in some cases, vertical position) of the text

And so on. Similarly, ParagraphStyle has subclasses like BulletSpan for bulleted lists.

You can implement your own custom subclasses of CharacterStyle and ParagraphStyle, though the book does not cover this subject at this time.

Loading Rich Text

The preview of this section took that left turn at Albuquerque.

Editing Rich Text

The preview of this section was traded for a bag of magic beans.

Saving Rich Text

The preview of this section left for Hollywood to appear in a reality TV show.

Manipulating Rich Text

The preview of this section was eaten by a grue.