Autosizing TextView Tutorial for Android: Getting Started

In this Android Autosizing TextView tutorial, you’ll learn how to use new TextView properties to build an app with text that autosizes, adapting dynamically to changes in height and width.

Version

  • Kotlin 1.3, Android 8.0, Android Studio 3

Android has released new properties for TextView which let you automatically resize text depending on the width and/or height of your text area. In this autosizing TextView tutorial, you’ll learn how to use this cool new feature.

Mobile apps use TextViews extensively. Sometimes, the developer has to use a fixed height or width, which makes resizing the font to always display the text challenging.

Starting with Android 8.0 (API level 26), you can set these new autosizing properties with the TextView class. Thanks to the Support Library 26.0, you can also use these on devices running Android 4.0 (API level 14) or later by using the TextViewCompat class.

Note: This tutorial assumes you are familiar with the basics of Android and Kotlin. If you are new to Android Development, check out our Android Tutorial for Beginners series. Just need to catch up on Kotlin? Take a look at Kotlin For Android: An Introduction

Getting Started

The project you’ll work with, Jokes, is an app that shows you a list of jokes. You can pick a joke to create an image with, add other quotes, change the background and share the result with your friends.

Use the Download Materials button at the top or bottom of this tutorial to download the starter project.

Once downloaded, open the starter project in Android Studio 3.2.1 or newer. Build and run it, and you’ll see the following screen:
List of Jokes

Selecting one of the jokes brings you to a new screen that shows only the joke you chose. You can add more text and customize the background. You can also move and pinch the TextViews. When you have finished customizing the page, you can share it with your friends.
Joke Detail

You may have noticed that much of the text in the List Screen is sometimes cut off. Also, resizing the text in the Detail Screen doesn’t adjust the font size to the frame of the TextView.

Resizing text view with constant font size

To fix these problems, you’ll need to modify the code to autosize the TextViews according to their width and height.

Review the project to familiarize yourself with the files:

  • JokeDetailActivity.kt: Shows a single joke and lets you add additional text, customize the background and share.
  • joke_item.xml: Is the layout for each of the list items in the List Screen
  • activity_detail.xml: Is the layout for the Detail Screen.

Configuring TextView Autosizing Properties

There are three options that you need to consider when configuring the Autosize properties: AutoSizeTextType, Granularity and Preset Sizes. You’ll learn about them in this section.

AutoSizeTextType

If you want to enable autosizing, you need to set the app:autoSizeTextType property to uniform in the xml. Otherwise, the default is none, which disables this autosizing feature.

Open joke_item.xml, which the List Screen uses, and change the emoji TextView with id @+id/emoji to include this attribute. It should now look like the following:

<TextView
  android:id="@+id/emoji"
  android:layout_width="50dp"
  android:layout_height="50dp"
  android:layout_marginStart="8dp"
  android:gravity="center"
  android:textColor="#000"
  app:autoSizeTextType="uniform"
  app:layout_constraintBottom_toBottomOf="@+id/jokeText"
  app:layout_constraintStart_toStartOf="parent"
  app:layout_constraintTop_toTopOf="parent"
  tools:text="😀" />

Notice that you have added app:autoSizeTextType="uniform" to enable autosizing.

Note: If you are using a minSdk lower than 26 in your own project when using this, you may see a warning. To get rid of it, change from TextView to android.support.v7.widget.AppCompatTextView.

Now, following the same pattern, change the joke TextView with id @+id/jokeText to add app:autoSizeTextType="uniform". It should now look like this:

<TextView
  android:id="@+id/jokeText"
  android:layout_width="0dp"
  android:layout_height="@dimen/joke_height"
  android:layout_marginStart="8dp"
  android:layout_marginEnd="8dp"
  android:gravity="center_vertical"
  android:textColor="#fff"
  app:autoSizeTextType="uniform"
  app:layout_constraintEnd_toEndOf="parent"
  app:layout_constraintStart_toEndOf="@+id/emoji"
  app:layout_constraintTop_toTopOf="parent"
  tools:text="Want to hear a joke about construction? I'm still working on it." />

Open activity_detail.xml and change the joke description TextView with the id @+id/jokeDescription the same way to be the following:

<TextView
  android:id="@+id/jokeDescription"
  android:layout_width="match_parent"
  android:layout_height="100dp"
  android:layout_gravity="center"
  android:layout_marginLeft="16dp"
  android:layout_marginRight="16dp"
  android:background="@color/colorPrimaryDark"
  android:gravity="center_vertical"
  android:padding="@dimen/joke_margin"
  android:textColor="#FFF"
  app:autoSizeTextType="uniform"
  tools:text="Want to hear a joke about construction? I'm still working on it." />

Build and run the application. You’ll notice that the TextViews in the List Screen and the Detail Screen now autosize correctly.

Joke List with autosize TextViews.
Detail Screen with autosize TextView

However, if you try to add a TextView in the Detail Screen, it won’t autosize when you pinch the view because it’s added at runtime.

To fix this, open JokeDetailActivity.kt and find the buildTextView() method. Replace the call to setTextSize(TypedValue.COMPLEX_UNIT_SP, 24f) with the following:

TextViewCompat.setAutoSizeTextTypeWithDefaults(this,
    TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM)

You’ve replaced the hardcoded font size of 24sp with the uniform AutoSizeTextType, but this time programmatically.

Note: For the autosizing to work properly, it’s important to set the width and the height to either match_parent or to a specific value in dps, either in xml or programmatically. Using wrap_content is not recommended because it may produce unexpected results.

Build and run the app again. Select a joke, add some additional text and resize the TextView. It should now scale properly.

Resizing joke and text

Granularity

If you want to customize the text further, you can set a range by configuring a minimum, maximum and step increment so that the TextView scales uniformly within the range.

Suppose your UX team has design guidelines that specify that the List Screen should have text with a minimum of 12sp and a maximum of 28sp with steps of 4sp.

Open joke_item.xml and change the joke TextView with the id @+id/jokeText to include the following:

app:autoSizeMaxTextSize="28sp"
app:autoSizeMinTextSize="12sp"
app:autoSizeStepGranularity="4sp"

Build and run the application and select a joke. What happens when you change the size of the joke text?

You should also make this change programmatically when new TextViews are added. Replace the call to setAutoSizeTextTypeWithDefaults() you added in JokeDetailActivity.ky buildTextView() with the following:

TextViewCompat.setAutoSizeTextTypeUniformWithConfiguration(this,
    12, 28, 4,
    TypedValue.COMPLEX_UNIT_SP)

Preset Sizes

Instead of using minimum, maximum and a step increment, you can specify preset values that the TextView can use when autosizing text.

Create an arrays.xml file under app ▸ src ▸ main ▸ res ▸ values with this content:

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <array name="autosize_text_sizes">
    <item>12sp</item>
    <item>16sp</item>
    <item>20sp</item>
    <item>24sp</item>
    <item>28sp</item>
  </array>
</resources>

Here you are using the same step increments as before, except that you can use whatever values you want.

Open joke_item.xml and change the joke TextView to replace this:

app:autoSizeMaxTextSize="28sp"
app:autoSizeMinTextSize="12sp"
app:autoSizeStepGranularity="4sp"

with this:

app:autoSizePresetSizes="@array/autosize_text_sizes"

To make this change programmatically, change that same line in setAutoSizeTextTypeWithDefaults() to:

TextViewCompat.setAutoSizeTextTypeUniformWithPresetSizes(this,
        intArrayOf(12, 16, 20, 24, 28),
        TypedValue.COMPLEX_UNIT_SP)

You can also get the values from the xml file you created by using context.resources.getIntArray(R.array.autosize_text_sizes) instead of creating the array manually with intArrayOf().

Build and run the app and play with resizing the TextView. Try changing the values in the array, then building and running the app again to see how resizing the TextView affects the scaling.

Where to Go From Here?

Congratulations! You’ve just learned how to use the autosizing TextView properties on Android.

You can download the final version of the project using the Download Materials button at the top or bottom of this tutorial.

Here are some great references to learn more about the subject:

If you have any questions or additional tips to share, please join in the forum discussion below!

Contributors

Comments