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.
Table of Contents
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 horizontallyandroid:autoSizeMaxTextSize
– Maximum text size for the TextViewandroid: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" />
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.
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
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="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://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:
This brings an end to this tutorial. You can download the project from the link below: