Coding Native Text: NSAttributedStrings (iOS), RichText (Windows Store apps) and Spannables (Android)


The most popular way to format text is often HTML. In iOS developers would (prior to iOS 7) use the full-blown UIWebView class, doing something like this:

UIWebView *localWebContent = [[UIWebView alloc] init];

[localWebContent loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"Text/page3" ofType:@"xhtml" inDirectory:@"Brochure/"]isDirectory:NO]]];

Windows developers also have a similar WebView approach available to them, and Android developers can import HTML into their text view using fromHTML like this:

TextView tv = (TextView) findViewById(R.id.myTextView); tv.setText(Html.fromHtml(getString(R.string.my_text)));

Introduction

The purpose of this post is to address how to get started with native (or core) text and move into sophisticated areas of text manipulation within iOS, Android and Windows Store apps.

iOS (Xcode)

I've already written a number of blogposts on NSAttributedStrings and the opportunities to place these within UITextViews in iOS. So instead of reworking those here, I'm simply going to link to them.

Previous posts

Making the Most of UITextView in iOS 7: NSTextStorage, NSLayoutManager, NSTextContainer and NSAttributedString

Drawing NSAttributedStrings with Superscripts and Subscripts (iOS/Xcode)

Creating an NSAttributedString from HTML (or RTF) in iOS 7 (Xcode) 

Paging and paginating the easy way with UITextView and UIScrollView in iOS 7 (Xcode)

Android (Eclipse)

If we want to move beyond a reliance on HTML in Android then we turn to the Spannable class. So let's do some stuff with it to show that it works.

// Text view tagged with @+id/textView in activity_main.xml
TextView v = (TextView) findViewById(R.id.textView);

// text string
String s = "Here's some text to play with";

// New Spannable created
Spannable span = new SpannableString(s);

// Set some text attributes across ranges
span.setSpan(new ForegroundColorSpan(Color.BLUE), 4, s.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
span.setSpan(new TextAppearanceSpan("sans-serif-thin", 3, 37, null, null), 4, s.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
span.setSpan(new SuperscriptSpan(), 8, 10, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

// Add span to TextView
v.setText(span);

You'll notice that we can add multiple spans to a piece of text and that the approach resembles that of NSAttributedStrings in iOS.

Note: There is the opportunity to access Layout methods and Paint methods from a TextView using getLayout() and getPaint().

Warning: When testing the getLayout() method, do not do this within onCreate or onStart methods. The text needs an opportunity to layout before it returns anything.

Installed fonts on Android are so limited that we do not even specify a family, it knows instead in this instance that from the type we want the newly available Roboto font

Further Reading – Android

SpannableString (StackOverflow)

TextAppearanceSpan (Android, Developer)

AttributedText (JavaForums)

Text overflow in TextView (StackOverflow)

Layout class (Android, Developer)

Canvas (Android, Developer)

the android.text.style package (Android, Developer)

TextAttribute class (Android, Developer)

AttributedCharacterIterator  (Android, Developer)

SpannableString (Android, Developer)

Windows Store apps (Visual Studio)

In Windows, begin with a Run of text, which can then have styles, such as bold and italic or font families, etc., applied. For a mulitple paragraph piece of text this is then added to a Paragraph object before finally being added to a RichTextBlock. The code below explains this (it has been placed in the constructor method of the MainPage):

public MainPage()
{
this.InitializeComponent();

// Create a Run of plain text
Run myRun = new Run();
myRun.Text = "My Run!";

// Change the text to bold
Bold myBold = new Bold();
myBold.Inlines.Add(myRun);

// Change fontsize
myBold.FontSize=30;

// Create a new Run of plain text
Run myNextRun = new Run();
myNextRun.Text = " My Next Run!";

// Change text to italic
Italic myNextItalic = new Italic();
myNextItalic.Inlines.Add(myNextRun);

// Change font size
myNextItalic.FontSize = 40;

// Create a Run of plain text and some bold text.
Run myFinalRun = new Run();
// Change font family
myFinalRun.FontFamily = new FontFamily("Impact");

// Add text
myFinalRun.Text = "Run101";

// Change font size
myFinalRun.FontSize = 30;

// Add the text to a span for the fun of it - you can delete the next two lines of code!!
Span myFinalRunSpan = new Span();
myFinalRunSpan.Inlines.Add(myFinalRun);

// Add superscript to variants - e.g. numerals and th, etc.
Typography.SetVariants(myFinalRunSpan, FontVariants.Superscript);

// Create a paragraph
Paragraph myParagraph = new Paragraph();
// Add bold run to para
myParagraph.Inlines.Add(myBold);
// Add italic run to para
myParagraph.Inlines.Add(myNextItalic);
// Create new paragraph
Paragraph myNextParagraph = new Paragraph();
// Add text to paragraph
myNextParagraph.Inlines.Add(myFinalRunSpan);
// Create rich text block
RichTextBlock myRTB = new RichTextBlock();
// add the two paragraphs
myRTB.Blocks.Add(myParagraph);
myRTB.Blocks.Add(myNextParagraph);

// Add RichTextBlock to page
this.Content = myRTB;
}

One of the really interesting things is the Typography class, which enables superscript to be applied specifically to numbers and things like th - what are known as font variants. The Typography class can also be used to form fractions. But this is only really the surface of displaying and editing RichText and there is plenty more to be learnt. Please use the further reading as a starting point.

Further reading – Windows

RichTextBlock Overview (Windows, Developer)

GlyphRun object (Windows, Developer)

Glyphs class (Windows, Developer)

Documents namespace (Windows, Developer)

Glyphs and TextBlock (Windows, Developer)


Endorse on Coderwall

Comments