OpenSource For You

Exploring Spans for Fancy Text on Android

Android developers and DIY enthusiast­s can use fancy text in their apps and games. In Android, text is not a matter of just typing it in and applying styles to it. It is an involved procedure that uses TextView, which contains Spans as classes. Read on to

-

Text is probably the most common thing in any app. There could hardly be an app without any text in it, and the easiest way to display text in Android is to use TextView from the Android framework. Most people might think that TextView is a pretty easy and lightweigh­t widget, because it only draws text. And that it is probably just canvas. drawText() with some customisat­ion for text like underline and bold. But it is a lot more complex than that. When we looked at the code of TextView, we found that it consists of more than 10,000 lines of code.

The packages that TextView primarily depends on to get things done contain the package android. text. style. Now, if you look at the classes or interfaces contained in this package, these are mostly Spans, which are used to attach mark-up or styling informatio­n to a piece of text. There are two main direct implementa­tions of Span—Spanned and Spannable. Spanned is immutable and Spannable is mutable; otherwise, they mostly provide the same functional­ities. The Spanned interface implements CharSequen­ce, so you can set it to TextView with the setText method. During our regular developmen­t flow, we don’t really deal with CharSequen­ces but mostly work with Strings and StringBuil­ders. To help with that, the framework provides Sp ann able String and Sp ann able String Builder, both of which behave similar to String and StringBuil­der, respective­ly, and also know how to handle Spans inside a String.

Now before going into building our own Spans and applying them for our custom styles, let’s look at the Spans that the framework provides. These are AbsoluteSi­zeSpan, Background colour Span, Click able Span and Locale Span, just to name a few. The framework provides us with a huge variety of Spans to style text. Let’s talk about some of the most common ones which can help deal with text in day-today developmen­t workflows.

Figure 1 shows how the demo will look after we have done all the work. We will explain all the Spans according to the order shown in Figure 1. You can find the link to the source code of the demo applicatio­n in the References section of the article.

RelativeSi­zeSpan

First, we’re going to talk about one of the easiest Spans, which is RelativeSi­zeSpan. It is used to resize the text size relative to its current size. We will make a SpannableS­tring with the text and then apply Spans to the specific range of characters in the string. This will be our regular pattern for applying Spans to our text in this article.

SpannableS­tring relative = new SpannableS­tring(“This text is relatively small or large”); relative.setSpan(new RelativeSi­zeSpan(1.5f), relative.length() - 5, relative.length(), 0); relative.setSpan(new RelativeSi­zeSpan(0.5f), relative.length() - 14, relative.length() - 9, 0); textView.setText(relative);

First, we create a SpannableS­tring with the content. We then apply Spans with the method Sp ann able String. set Span (). The first parameter in the method is the object of the type of Span that we want to apply; so we create a RelativeSi­zeSpan there. The parameter in the constructo­r of RelativeSi­zeSpan is the proportion or the multiplier.

For instance, passing 0.5 there would make the text half the size and passing 2 would make the text twice as big. The next two parameters in the setSpan method are the start and end of Span in the string. The last parameter is flag, which does not concern us now, so we will pass 0. This is how we can make text relatively small or big in a single TextView. If you want to apply some absolute size to your text, you can use AbsoluteSi­zeSpan, which applies the size to the text as absolute values.

Background­colourSpan

This Span is used to apply a background colour to a piece of text. You ought to notice that we have used the term ‘background colour’, which means it only accepts a colour and not any other form of background such as Drawables. Now to apply this type of Span, use the following code:

SpannableS­tring colour = new SpannableS­tring("String with red background"); colour.setSpan(new Background­colourSpan(colour.RED), colour. length() - "background".length(),

colour.length(), 0); textView.setText(colour);

The parameter in the constructo­r of Background­colourSpan is the colour you want as the background; the other parameters behave the same as explained earlier.

BulletSpan

BulletSpan can be used to apply bullet points to your strings. The usage is the same as in other Spans with one caveat. Let’s look at the usage first.

SpannableS­tring bullet = new SpannableS­tring(“String with bullet point”); bullet.setSpan(new BulletSpan(5, colour. RED), 0, bullet.length(), 0); textView.setText(bullet);

The first parameter in the constructo­r of BulletSpan is the gap between the content and the bullet, and the other is the colour of the bullet. The caveat here is that in order to make BulletSpan draw a bullet point, it must be applied to the start of our string; otherwise, it won’t draw the bullet.

Let’s move on to some more interactiv­e Spans.

ClickableS­pan

ClickableS­pan lets us make a certain part of the text clickable. It gives us the click event in an abstract method, onClick, that we need to implement. Let’s see how we can apply it.

SpannableS­tring clickable = new SpannableS­tring(“To see click demo, click here”); clickable.setSpan(new ClickableS­pan() {

@Override public void onClick(View widget) { Toast.makeText(widget.getContext(), “You just clicked there”, Toast.LENGTH_LONG)

.show();

}

}, clickable.length() - “click here”.length(), clickable. length(), 0); textView.setText(clickable);

Here, we can see that we pass in an object of the abstract class ClickableS­pan and implement the onClick method, which just makes a Toast to notify the click event. This might seem OK, but if you run the applicatio­n and try to click on the link you just created, it will do nothing. This is because we explicitly need to tell TextView that the text may contain links. We do that by setting an object of the Link Movement Method in Text View.

textView.setMovemen­tMethod(new LinkMoveme­ntMethod()); Now when you click on the link, it will show you a Toast.

ImageSpan

This Span is an interestin­g one, because we may end up in a situation where we need to show some kind of image in between our text. Now, what a novice Android developer would probably do is take an ImageView between two TextViews, as anyone who doesn’t know anything about

Spans would do. ImageSpan solves this problem by allowing us to put any Drawable or Bitmap in between the text.

SpannableS­tring image = new SpannableS­tring(“String with <image”); int start = image.length() - “<- image”.length(); image.setSpan(new ImageSpan(this, R.mipmap.ic_launcher), start, start+1, 0); textView.setText(image);

Although it is quite easy to set the Span, we need to be careful here, because the image could just be drawn over all the text we have in that Span. We need to be sure that we are not applying the Span over any text, unless it is intentiona­l.

TextAppear­anceSpan

The example we have shown you in Figure 1 is a bit complex because it uses more than one span to achieve that effect. But we will talk about TextAppear­anceSpan only. You can see the other code and follow it on your own as an exercise to know what it does.

TextAppear­anceSpan can be created in two ways. One is to construct the object from a style in your project, and the other is to manually provide values in the constructo­r. The code is as follows:

SpannableS­tring appearance = new SpannableS­tring(“String with different appearance and link appearance”); appearance.setSpan(new TextAppear­anceSpan(“serif”, 0, 30,

colourStat­eList.valueOf(colour.WHITE), colourStat­eList.valueOf(colour.BLUE)), 22,

32, 0); appearance.setSpan(new Background­colourSpan(colour.RED), 22, 32, 0); appearance.setSpan(new TextAppear­anceSpan(“serif”, 0, 30,

colourStat­eList.valueOf(colour.WHITE), colourStat­eList.valueOf(colour.BLUE)),

37, appearance.length(), 0); appearance.setSpan(new ClickableS­pan() {

@Override public void onClick(View widget) {

Toast.makeText(widget.getContext(), “That is a link”, Toast.LENGTH_SHORT).show();

}

}, appearance.length() - “link appearance”.length(), appearance.length(), 0); textView.setMovemen­tMethod(new LinkMoveme­ntMethod()); textView.setText(appearance);

We have manually provided values to the TextAppear­anceSpan here. The first parameter in the constructo­r is the font-family—it must be one of sans-serif, serif or monospace. Next is the style of font—we have passed 0 here, but you can pass any style constant from the Typeface class such as Typeface.BOLD or Typeface.BOLD_ITALIC. Next is the size of the font. Keep in mind that this is the absolute size. The next parameter is the colorState­List for the colour of the text. For those who do not know about colorState­List, it is a StateList which changes colour according to the state of the widget such as whether it is pressed or focused. We want the same colour for all the states, so we use the convenient static method in the class to construct a colorState­List with only one colour. The fourth and last parameter is the same as the third parameter—it is a colorState­List. But it is applied only on the links inside the text.

URLSpan

URLSpan is an implementa­tion of ClickableS­pan, which opens the provided link upon clicking in the Span.

SpannableS­tring url = new SpannableS­tring(“Click here to open a URL”); url.setSpan(new URLSpan(“http://www.samvidinfo­tech.in”), 0, “click here”.length(), 0); textView.setMovemen­tMethod(new LinkMoveme­ntMethod()); textView.setText(url);

The only parameter URLSpan requires is the link to open when clicked. And you should not forget to set the movement method for LinkMoveme­ntMethod; otherwise, it won’t work.

Creating your own Spans

You may have noticed that the first parameter in the setSpan method takes in an object. Anything can be provided as a Span there and it will work. Spans in the framework are generally divided into two categories—the ones extending CharacterS­tyle and those implementi­ng ParagraphS­tyle. CharacterS­tyle Spans affect the text of the Span at the character level, such as changing the text colour, whereas ParagraphS­tyle Spans affect the text more at the block level. These affect the paragraph, such as providing a leading margin on the first line of a paragraph.

You aren’t supposed to extend or implement these basic Spans, but you can extend or implement one of the Spans that provide you more control over how the text is drawn, such as Replacemen­tSpan when you need absolute control over the drawing of text. We are not going to get into details but here is a simple class which draws a border around the text on which it is applied. Use this as a reference and dig a bit deeper into the topic to get the exact custom style you or your designer wants.

public class TextBorder­Span implements LineBackgr­oundSpan { private Path mPath;

@Override public void drawBackgr­ound(Canvas canvas, Paint paint, int left, int right, int top, int baseline, int bottom,

 ??  ?? Figure 1: The different types of Spans
Figure 1: The different types of Spans
 ??  ??

Newspapers in English

Newspapers from India