Android Auto-sizing TextView

Filed Under: Android

In this tutorial, we’ll look at how we can implement TextView such that it auto resizes itself based on the available space and properties specified in our Android Application.

Auto-Sizing TextView

Auto-sizing TextView was introduced with Android Oreo. Provided you set the required properties, the text size would automatically change inside its view. Auto-sizing TextView supports backward compatibility all the way till API 4.

To use Auto-sizing TextView you must use SDK 26 dependency or above:


implementation 'com.android.support:appcompat-v7:26.1.0'

Following are the core properties you must add on the TextView to enable Auto-sizing TextView:

  • android:autoSizeTextType – This is set to the value uniform or none. Uniform sizes the text uniformly vertically and horizontally
  • android:autoSizeMaxTextSize – Maximum text size for the TextView
  • android:autoSizeMinTextSize – Minimum text size for the TextView

An Auto-sizing TextView can be defined in the xml as:


<TextView
        android:id="@+id/autoTextView"
        android:layout_width="match_parent"
        android:layout_height="125dp"
        android:text="Resizable TextView here."
        android:autoSizeMaxTextSize="100sp"
        android:autoSizeMinTextSize="12sp"
        android:autoSizeTextType="uniform" />
For an Auto-sizing TextView to work properly it is recommended to NOT use WRAP_CONTENT.

How is the text auto-sized?

There are three ways to do it:

  • Default – Size changes happen by 1 px. That means granularity is 1 px
  • Granularity – This is a dimension by which the text size increases or decreases in steps between the minimum and maximum text size. Example : android:autoSizeStepGranularity="2sp" increments/decrements the text size by 2 sp.
  • Presets – This is used to auto-size the text from an array of predefined text size values.

Using Presets

We can define the predefined in an arrays.xml in the values folder.


<resources>
  <array name="autosize">
    <item>10sp</item>
    <item>30sp</item>
    <item>20sp</item>
    <item>40sp</item>
    <item>100sp</item>
  </array>
</resources>

Set this in the TextView as:


<TextView
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:autoSizeTextType="uniform"
    app:autoSizePresetSizes="@array/autosize" />


Auto-size for Pre-Oreo Devices

The above properties work fine only on Android Oreo and above. To make it compatible with the older version we need to do two things:

  • Use AppCompatTextView widget in place of TextView
  • Use app: nomenclature

Define the Auto-size TextView in the XML as:


<android.support.v7.widget.AppCompatTextView
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:text="TextView"
        app:autoSizeMaxTextSize="100sp"
        app:autoSizeMinTextSize="8sp"
        app:autoSizeStepGranularity="2sp"
        app:autoSizeTextType="uniform"
        />


Auto-size TextView programmatically

To set properties on the Auto-size TextView programmatically we use the TextViewCompat class.

android auto-size textviewcompat

You need to pass the TextView instance and the respective sizes for the properties.

Set the autoSize text types as: TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE or TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM.

Setting Presets programmatically:

To set the presets programmatically you need to define the arrays.xml differently.


<?xml version="1.0" encoding="utf-8"?>
<resources>
    <array name="autosize">
        <item>20</item>
        <item>40</item>
        <item>50</item>
        <item>60</item>
        <item>70</item>
    </array>
</resources>

To set it on the TextView do the following:


TextViewCompat.setAutoSizeTextTypeUniformWithPresetSizes(textView, getResources().getIntArray(R.array.autosize), TypedValue.COMPLEX_UNIT_SP);

Let’s build an android application that demonstrates the various use cases of Auto-sizing TextView.


Project Structure

android auto-size textview project

Code

The code for the activity_main.xml layout is given below:


<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="0dp"
        android:layout_height="125dp"
        android:background="@android:color/black"
        android:text="Not resizable TextView. The text size is fixed here."
        android:textColor="@android:color/white"
        app:layout_constraintEnd_toStartOf="@+id/autoTextView"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintHorizontal_chainStyle="packed"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/editTextPreset" />

    <android.support.v7.widget.AppCompatTextView
        android:id="@+id/autoTextView"
        android:layout_width="0dp"
        android:layout_height="125dp"
        android:background="@android:color/black"
        android:text="Resizable TextView here. This can vary the text size based on it."
        android:textColor="@android:color/white"
        app:autoSizeMaxTextSize="100sp"
        app:autoSizeMinTextSize="12sp"
        app:autoSizeStepGranularity="2sp"
        app:autoSizeTextType="uniform"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/textView"
        app:layout_constraintTop_toBottomOf="@+id/editTextPreset" />

    <android.support.v7.widget.AppCompatTextView
        android:id="@+id/autoTextViewDynamic"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:layout_marginEnd="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:text="TextView"
        app:autoSizeMaxTextSize="100sp"
        app:autoSizeMinTextSize="8sp"
        app:autoSizeStepGranularity="2sp"
        app:autoSizeTextType="uniform"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:ems="10"
        android:hint="Enter here"
        android:maxLines="1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/autoTextViewDynamic" />


    <EditText
        android:id="@+id/editTextPreset"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:ems="10"
        android:hint="Enter here for preset size changes"
        android:maxLines="1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/editText" />


    <android.support.v7.widget.AppCompatTextView
        android:id="@+id/autoTextViewEllipsize"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_marginTop="16dp"
        android:ellipsize="end"
        android:maxLines="1"
        android:text="Auto sizing TextView with ellipsize at the end. AppCompat TextVie2"
        app:autoSizeMaxTextSize="100sp"
        app:autoSizeMinTextSize="16sp"
        app:autoSizeStepGranularity="2sp"
        app:autoSizeTextType="uniform"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView" />

</android.support.constraint.ConstraintLayout>

We’ve added an ellipisize property on one of the Auto-sizing TextView. This way if the content is filled at min text size the remaining Text is truncated

The code for the MainActivity.java class is given below:


package com.journaldev.androidautosizingtextview;

import android.support.v4.widget.TextViewCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.TypedValue;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final TextView txtAutoSizeTextViewDynamic = findViewById(R.id.autoTextViewDynamic);
        final TextView textView = findViewById(R.id.textView);
        EditText editText = findViewById(R.id.editText);
        EditText editTextWithPresetChanges = findViewById(R.id.editTextPreset);

        editText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {



            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

                txtAutoSizeTextViewDynamic.setText(charSequence.toString());

            }

            @Override
            public void afterTextChanged(Editable editable) {

            }
        });

        editTextWithPresetChanges.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                TextViewCompat.setAutoSizeTextTypeUniformWithPresetSizes(textView, getResources().getIntArray(R.array.autosize), TypedValue.COMPLEX_UNIT_SP);
            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                textView.setText(charSequence);
            }

            @Override
            public void afterTextChanged(Editable editable) {

            }
        });
    }
}

We’ve added TextWatchers on two of the EditTexts which will update the Auto-sizing TextViews whenever the edit text is changed.

We’ve changed the normal text view to an auto-sizing one when text is entered in the second EditText.

The output of the above application in action is given below:

android auto-sizing textview output

This brings an end to this tutorial. You can download the project from the link below:

Leave a Reply

Your email address will not be published. Required fields are marked *

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages