Android spannable text size

Getting Started with Spannables on Android

Begin formatting text like a pro!

T ext, probably the most basic element you get to work with on Android, and sometimes we have to format certain parts of our text. Formatting helps place emphasis on text, indicating that the formatted parts of text mean more when compared to plain parts. Formatting options include underline, bold, italics, strikethrough and many more. Android provides a number of options to its’ developers when it comes to formatting text. A direct approach is by using HTML markup to define sections of our text to be formatted, tags like the — underline, — bold and — italics do just that. Android properly helps us convert the markup provided into nicely formatted text.

Using XML

Or Code

We have an awesome option for formatting, don’t we? but that’s not all there is to formatting.

Formatting is the arrangement of a material in a particular layout, shape, size and general makeup — Merriam-Webster

Formatting goes beyond boldening or underlining text, we have a pool of design possibilities we can replicate. For example, we might want to set the colour of a fraction of our text differently or its size or its background, whatever. These designs are achievable using spannables without having to worry about too much.

Our First Spannable

To get started, create a new android studio project with your preferred project name and add this to the activity_main.xml . In the code below, we have a parent LinearLayout and five textviews. Android treats spannables like basic text so we can easily set the formatted text to the textviews, hence the usage of textviews.

In the layout above, we created five TextView s to hold differently formatted text, we’d go through them one after the other, starting with the bold format. But before that, let’s take a moment to understand the general structure of how spannables are set up and how the formatting takes place.

How are spannables set up?

When it comes to using Spannables, we can create them in three ways. By using any of the SpannedString, SpannableString and the SpannableStringBuilder classes. Each of these classes has features that differentiate them, the differences are outlined below.

  1. SpannedString — This class does not allow modifications to the text set into the Spannable. No modifications to the text and no modifications to the design (the spans). In other words, it’s immutable.
  2. SpannableString — This class allows for modifications of the design/styles added to the text, but no direct modification of the text used by the Spannable.
  3. SpannableStringBuilder — This class allows for modifications to the text itself and its designs.

The key takeaway here can be summarised as such:

Use SpannedString when you want to set the text and design once without any further modifications, SpannableString when you won’t be making any changes to the text but to the design and SpannableStringBuilder when you’d be making changes to both the underlying text and the design.

Format For Spannables

Now that we have a clear view of the types of spans we can use, let’s dig deeper into their general structure. Spannables you’d use in the future generally come in this fashion:

Our spannable object provides a setSpan method we can use to apply different span styles to sections of our text. It takes in four arguments, let’s dive in!

  1. what — This refers to the actual span style we would be applying, think of it as an object that instructs our spannable to apply a certain style to the text.
  2. startIndex — Remember our spannables deal with text? Right. The startIndex parameter denotes the index where the text to be formatted begins. Say the text to be formatted is thyself in steady thyself , we could deduce that the startIndex for this text is 7.
  3. endIndex — This does pretty much the opposite of what the startIndex does, it denotes the index of the character that ends the text to be formatted. Using our example from our startIndex explanation, our endIndex is the index of the letter f in thyself , so that would make it 13.
  4. flags — This indicates how the text provided to the spannables should be treated, we have various values that can be assigned to this parameter position, examples are SPAN_EXCLUSIVE_EXCLUSIVE , SPAN_EXCLUSIVE_INCLUSIVE , SPAN_INCLUSIVE_INCLUSIVE and many more. A detailed explanation is provided below.

Spannable Flags

As explained above, spannable flags indicate how the Spanning process should treat the text to be spanned. Some of the flags we can use are explained below.

  1. SPAN_INCLUSIVE_INCLUSIVE: This allows new text to be added to both the starting and end points of the text.
  2. SPAN_INCLUSIVE_EXCLUSIVE: This allows new text to be added to the starting point, but not to the end.
  3. SPAN_EXCLUSIVE_INCLUSIVE: This does not allow text to be added to the starting point, but the end.
  4. SPAN_EXCLUSIVE_EXCLUSIVE: This does not allow text to be added to the start and end points of the text.
Читайте также:  Калькулятор для андроид для android

You can read about other span flags here, since we have covered the general structure of applying spans, and dug deep into it’s required parameters, this seems like a good time to write our first span.

The Bold Span

Let’s start by retrieving a reference to a TextView in our layout, and then setting up a function to apply the spanning. We do that by writing:

Источник

Использование RichText в Android. Spannable

Привет Хабраобщество! Эта статья об использовании Spannable в Android. Предназначен он для стилизации текста. Если Вас интересует как реализовать нечто подобное:

тогда добро пожаловать под кат. Статья ориентированная на разработчиков, у которых нет большого опыта разработки под Android.

Теория

Spannable — интерфейс, который описывает маркировку обычного текста некими объектами. Задание этих объектов заключается в присвоению части текста некоторого определенного стиля. Такими маркировочными объектами могут быть экземпляры классов, которые реализуют интерфейс ParcelableSpan. Добавление маркировки осуществляется методом:

Удаление, соответственно, методом:

Теории немного, перейдем сразу к практике.

Практика

Для освоения практики необходимо создать android проект или открыть уже существующий. Я создал чистый проект, на главную activity разместил один TextView. Идем в метод, где будем инициализировать наш TextView (у меня onCreate) и добавляем следующий текст:

Итак, разберемся что же мы написали. SpannableString — класс, который реализует интерфейс Spannable (с другими реализациями можно ознакомится на сайте официальной документации). UnderlineSpan — реализация ParcelableSpan, маркирует часть текста как подчеркнутый (в нашем примере это с 8-ой по 17-тую букву). Флаг Spanned.SPAN_EXCLUSIVE_EXCLUSIVE обозначает, что наш span не будет расширятся на вставки текста слева или справа от маркированной части. (Со всеми флагами можно ознакомится на официальном сайте, при работе с текстами readonly они не столь важны).

Также здесь ми использовали еще одну реализацию ParcelableSpanStyleSpan. Как вы уже догадались, с его помощью можно маркировать текст как полужирный (Typeface.BOLD) или курсив (Typeface.ITALIC).

С кодом ми разобрались, запускаем наш проект и смотрим на результат. Текст должен выглядеть следующим образом:

Хорошо, идем дальше: добавим на наше activity кнопку, а в инициализирующий метод следующий текст:

На этот раз не будем разбирать код, ничего нового уже для нас нет. Мы использовали маркировку курсивом, которую я описал выше. Запускаем, смотрим.

Мы смогли вывести стилизованный текст на кнопку.

Пойдем еще дальше, реализуем обработчик события клика кнопки, в нем пишем следующий код:

Здесь у нас появляется новый класс — ForegroundColorSpan, который задает цвет нашему тексту, в примере мы задали зеленой. Мы его используем в паре с StyleSpan. Запускаем приложение, смотрим на результат.

Мы смогли запихнуть стилизованный текст даже в Toast. Также мы показали, что для одной части текста можно использовать несколько маркировок со стилями.

Вместо заключения

В примере мы использовали только некоторые из доступных стилей, больший список можно посмотреть на сайте разработчиков. Думаю вы сможете поэкспериментировать с ними.

Целью статьи было в доступной форме показать столь сильный и простой инструмент для стилизации своего приложения разработчикам, которые не знали о его существовании или просто не использовали его. Надеюсь что статья будет полезна.

Источник

Spantastic text styling with Spans

To style text in Android, use spans! Change the color of a few characters, make them clickable, scale the size of the text or even draw custom bullet points with spans. Spans can change the TextPaint properties, draw on a Canvas , or even change text layout and affect elements like the line height. Spans are markup objects that can be attached to and detached from text; they can be applied to whole paragraphs or to parts of the text.

Let’s see how to use spans, what spans are provided out of the box, how to easily create your own and finally how to test them:

Styling text in Android

Android offers several ways of styling text:

  • Single style — where the style applies to the entire text displayed by a TextView
  • Multi style — where several styles can be applied to a text, at character or paragraph level

Single style implies styling of the entire content of the TextView, using XML attributes or styles and themes. This approach is an easy solution and works from XML but doesn’t allow styling of parts of the text. For example, by setting textStyle=”bold” , the entire text will be bold; you can’t define only specific characters to be bold.

Multi style implies adding several styles to the same text. For example, having one word italic and another one bold. Multi style can be achieved using HTML tags, spans or handling custom text drawing on the Canvas.

HTML tags are easy solutions for simple problems, like making a text bold, italic, or even displaying bullet points. To style text containing HTML tags, call Html.fromHtml method. Under the hood, the HTML format is converted into spans. Please note that the Html class does not support all HTML tags and css styles like making the bullet points another colour.

Читайте также:  Android send at command

You manually draw the text on Canvas when you have styling needs that are not supported by default by the platform, like writing text that follows a curved path.

Spans allow you to implement multi-style text with finer grained customisation. For example, you can define paragraphs of your text to have a bullet point by applying a BulletSpan . You can customise the gap between the text margin and the bullet and the colour of the bullet. Starting with Android P, you can even set the radius of the bullet point. You can also create a custom implementation for the span. Check out “Create custom spans” section below to find out how.

You can combine single style and multi style. You can consider the style you apply to the TextView as a “base” style. The spans text styling is applied “on top” of the base style and will override the base style. For example, when setting the textColor=”@color.blue” attribute to a TextView and applying a ForegroundColorSpan(Color.PINK) for the first 4 characters of the text, then, the first 4 characters will use the pink colour set by the span, and the rest of the text, the colour set by the TextView attribute.

Applying Spans

When using spans, you will work with one of the following classes: SpannedString , SpannableString or SpannableStringBuilder . The difference between them lies in whether the text or the markup objects are mutable or immutable and in the internal structure they use: SpannedString and SpannableString use linear arrays to keep records of added spans, whereas SpannableStringBuilder uses an interval tree.

Here’s how to decide which one to use:

  • Just reading and not setting the text nor the spans? -> SpannedString
  • Setting the text and the spans? -> SpannableStringBuilder
  • Setting a small number of spans ( SpannableString
  • Setting a larger number of spans (>

For example, if you’re working with a text that doesn’t change, but to which you want to attach spans, you should use a SpannableString .

All of these classes extend the Spanned interface, but the classes that have mutable markup ( SpannableString and SpannableStringBuilder ) also extend from Spannable .

Spanned -> immutable text with immutable markup

Spannable (extends Spanned )-> immutable text with mutable markup

Apply a span by calling setSpan(Object what, int start, int end, int flags) on the Spannable object. The what Object is the marker that will be applied from a start to an end index in the text. The flag marks whether the span should expand to include text inserted at their starting or ending point, or not. Independent of which flag is set, whenever text is inserted at a position greater than the starting point and less than the ending point, the span will automatically expand.

For example, setting a ForegroundColorSpan can be done like this:

Because the span was set using the SPAN_EXCLUSIVE_ INCLUSIVE flag, when inserting text at the end of the span, it will be extended to include the new text:

If the span is set with Spannable.SPAN_EXCLUSIVE_EXCLUSIVE flag, inserting text at the end of the span will not modify the end index of the span.

Multiple spans can be composed and attached to the same text segment. For example, text that is both bold and red can be constructed like this:

Framework spans

The Android framework defines several interfaces and abstract classes that are checked at measure and render time. These classes have methods that allow a span to access objects like the TextPaint or the Canvas .

The Android framework provides 20+ spans in the android.text.style package, subclassing the main interfaces and abstract classes. We can categorize spans in several ways:

  • Based on whether span changes only appearance or also the text metric/layout
  • Based on whether they affect text at character or at paragraph level

Appearance vs metric affecting spans

The first category affects character-level text in a way that modifies their appearance: text or background colour, underline, strikethrough, etc., that triggers a redraw without causing a relayout of the text. These spans implement UpdateAppearance and extend CharacterStyle . CharacterStyle subclasses define how to draw text by providing access to update the TextPaint .

Metric affecting spans modify text metrics and layout, therefore the object that observes the span change will re-measure the text for correct layout and rendering.

For example, a span that affects the text size will require re-measure and layout, as well as re-drawing. These spans usually extend the MetricAffectingSpan class. This abstract class allows subclasses to define how the span affects text measurement, by providing access to the TextPaint . Since MetricAffectingSpan extends CharacterSpan , subclasses affect the appearance of the text at character level.

You might be tempted to always re-create the CharSequence with text and markup and call TextView.setText(CharSequence) . But this will almost always trigger a re-measuring and re-drawing of the layout and extra objects being created. To decrease the performance hit set the text with TextView.setText(Spannable, BufferType.SPANNABLE) and then, when you need to modify the spans, retrieve the Spannable object from the TextView by casting TextView.getText() to Spannable . We’ll go into more details on what’s going on under the hood with TextView.setText and different performance optimisations in a further post.

For example, consider the following Spannable object set and retrieved like this:

Now, when we set spans on the spannableText , we don’t need to call textView.setText again because we’re modifying directly the instance of the CharSequence object held by TextView .

Here’s what happens when we set different spans:

Case 1: Appearance affecting span

Since we attached an appearance affecting span, TextView.onDraw is called but not TextView.onLayout . The text is redrawn, but the width and height will be the same.

Case 2: Metric affecting span

Because the RelativeSizeSpan changes the size of the text, the width and height of the text can change and the way text is layed out (for example, a particular word may fall into the next line now, without the TextView size changing). The TextView needs to compute the new size so onMeasure and onLayout are called.

Character vs paragraph affecting spans

A span can either affect the text at the character level, updating elements like background colour, style or size, or a the paragraph level, changing the alignment or the margin of the entire block of text. Depending on the needed styling, spans either extend CharacterStyle or implement ParagraphStyle . Spans that extend ParagraphStyle must be attached from the first character to the last character of a single paragraph, otherwise the span will not be displayed. On Android paragraphs are defined based on new line ( \n ) character.

For example, a CharacterStyle span like BackgroundColorSpan can be attached to any characters in the text. Here we’re attaching it from the 5th to the 8th character:

A ParagraphStyle span, like QuoteSpan , can only be attached from the start of a paragraph, otherwise the line and the text margin don’t appear. For example, “ Text is \n spantastic” contains a new line on the 8th character of the text, so we can attach the QuoteSpan to it and just the paragraph starting from there will be styled. If we attached the span to any position other than 0 or 8, the text would not be styled at all.

Creating custom spans

When implementing your own span, you will need to decide whether your span affects the text at character or paragraph level and whether it also affects the layout or just the appearance of the text. But, before writing your own implementations from scratch, check whether you can use the functionality provided in the framework spans.

  • Affecting text at the character level -> CharacterStyle
  • Affecting text at the paragraph level -> ParagraphStyle
  • Affecting text appearance -> UpdateAppearance
  • Affecting text metrics -> UpdateLayout

Let’s say that we need to implement a span that allows increasing the size of the text with a certain ratio, like RelativeSizeSpan , and setting the color of the text, like ForegroundColorSpan . To do this, we can extend the RelativeSizeSpan and, since this provides callbacks for updateDrawState and updateMeasureState , we can override the drawing state callback and set the colour of the TextPaint .

Note: the same effect can be achieved by applying both a RelativeSizeSpan and ForegroundColorSpan to the same text.

Testing custom spans implementation

Testing spans means checking that indeed the expected modifications have been made on the TextPaint or that the correct elements have been drawn on to your Canvas. For example, consider the custom implementation of a span that adds a bullet point, of a specified size and color to a paragraph, together with a gap between the left margin and the bullet point. See the implementation in the android-text sample. To test this class implement an AndroidJUnit test, checking that indeed:

  • A circle is drawn on the canvas, of a specific size
  • Nothing is drawn if the span is not attached to text
  • The correct margin is set, based on the constructor parameters values

Testing the Canvas interactions can be done by mocking the canvas, passing the mocked object to the drawLeadingMargin method and verifying that the correct methods have been called, with the correct parameters.

Check out the rest of the tests in the BulletPointSpanTest .

Testing spans usage

The Spanned interface allows both setting and retrieving spans from text. Check that the correct spans are added at the correct locations by implementing an Android JUnit test. In the android-text sample we’re converting bullet point markup tags to bullet points. This is done by attaching BulletPointSpans to the text, at the correct location. Here’s how it can be tested:

Check out MarkdownBuilderTest for more test examples.

Note: if you need to iterate through the spans outside tests, use Spanned#nextSpanTransition instead of Spanned#getSpans as it’s more performant.

Spans are a powerful concept, deeply embedded in the text rendering functionality. They give access to components like TextPaint and Canvas that allow a highly customisable way of styling text on Android. In Android P we’ve added extensive documentation to the framework spans so, before implementing your own, check out what’s available.

Источник

Читайте также:  Pokerstars не грузится лицензионное соглашение android
Оцените статью