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 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:
TextViewCompat class is compatible with all android versions (up to 4.0)?
or do we still need to do something for making it compatible for pre Oreo device