Olson CloudWorks 🚀

Auto-fit TextView for Android

September 19, 2026

Auto-fit TextView for Android

Have you ever struggled with text overflowing in your Android app’s user interface? Dealing with dynamic content or varying screen sizes can make it challenging to ensure your text always fits neatly within its designated space. The Auto-fit TextView for Android is a powerful solution that automatically adjusts the text size to fit within the TextView’s bounds. This prevents truncation and ensures a cleaner, more professional look and feel for your application. This technique is especially useful when dealing with localization and varying content lengths that may come as a result. By leveraging the capabilities of auto-sizing, you can create more responsive and user-friendly Android applications that adapt gracefully to different devices and screen resolutions.

Understanding Auto-fit TextView

The Auto-fit TextView for Android is a feature introduced in Android API level 17 (Android 4.2, Jelly Bean) and significantly enhanced in API level 26 (Android 8.0, Oreo) with the introduction of support library for older versions. It dynamically adjusts the text size of a TextView to completely fill the available space. This is particularly useful when dealing with variable-length text or supporting multiple screen sizes. Before auto-sizing, developers often had to manually calculate text sizes or resort to workarounds like using ellipsize to truncate text, which isn’t always the best user experience. Auto-fit TextView eliminates these manual adjustments, making your layouts more flexible and maintainable. The implementation is achieved through XML attributes or programmatically through Java/Kotlin code, offering versatility in application development.

One of the key advantages of using Auto-fit TextView for Android is its ability to maintain readability. By automatically scaling the text, the TextView ensures that users can always read the full content without having to scroll or zoom. This is especially important for user interfaces that require displaying critical information, such as error messages, labels, or short descriptions. Furthermore, using auto-sizing promotes a more consistent look and feel across different devices, as the text will always adapt to the available space, regardless of screen size or resolution. This leads to a more polished and professional application design.

Consider a scenario where you’re developing a news application. The headlines displayed on the main screen might vary significantly in length depending on the article topic. Using a regular TextView with a fixed text size could lead to some headlines being truncated while others have excessive white space. By implementing Auto-fit TextView for Android, you ensure that all headlines, regardless of their length, are displayed in full and at an optimal size, providing a better user experience. This adaptive behavior is crucial for creating applications that cater to diverse content and screen dimensions.

Implementing Auto-fit TextView

Implementing Auto-fit TextView for Android is straightforward. There are primarily two ways to achieve this: using XML attributes within your layout file or programmatically through Java/Kotlin code. The XML approach is generally simpler and more convenient for static configurations, while the programmatic approach provides more flexibility for dynamic adjustments based on runtime conditions.

To implement using XML, you need to add the app:autoSizeTextType attribute to your TextView in the layout file. The possible values are none (default), uniform (scales text uniformly to fit), and granularity (allows finer control over text size scaling). If you choose uniform, the TextView will automatically adjust its text size to fit within its bounds. For more control, you can use granularity along with other attributes like app:autoSizeMinTextSize, app:autoSizeMaxTextSize, and app:autoSizeStepGranularity to define the minimum and maximum text sizes and the step size for scaling. Below is an example of how to implement this in XML:

<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Your Dynamic Text Here" app:autoSizeTextType="uniform" app:autoSizeMinTextSize="12sp" app:autoSizeMaxTextSize="20sp" app:autoSizeStepGranularity="2sp"/> 

For programmatic implementation, you can use the TextViewCompat class from the androidx.core.widget package. This class provides methods like setTextAppearance() and setAutoSizeTextTypeWithDefaults() to control the auto-sizing behavior programmatically. This method is particularly useful when you need to dynamically adjust the auto-sizing properties based on user input or other runtime conditions. This provides granular control over how the Auto-fit TextView for Android resizes itself based on external data.

Steps for Programmatic Implementation

  1. Add the androidx.core:core-ktx dependency to your build.gradle file.
  2. Get a reference to your TextView in your Activity or Fragment.
  3. Use TextViewCompat.setAutoSizeTextTypeWithDefaults(textView, TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM) to enable auto-sizing with default settings.
  4. Optionally, use TextViewCompat.setAutoSizeTextTypeUniformWithConfiguration(textView, minTextSize, maxTextSize, stepGranularity, TypedValue.COMPLEX_UNIT_SP) to customize the auto-sizing parameters.

Best Practices and Considerations

While Auto-fit TextView for Android is a powerful tool, it’s essential to use it judiciously and be aware of its limitations. Overusing auto-sizing can lead to readability issues if the text is scaled down too much. It’s crucial to carefully consider the range of text sizes and the available space to ensure that the text remains legible. Proper planning and testing are crucial to avoid creating unintended user experience problems.

Here is a featured snippet-optimized paragraph: To achieve optimal performance with Auto-fit TextView for Android, it’s recommended to set appropriate minimum and maximum text sizes. Defining these boundaries prevents the text from becoming too small or too large, ensuring readability and a consistent user interface. The autoSizeMinTextSize and autoSizeMaxTextSize attributes in XML or the corresponding methods in Java/Kotlin allow you to set these limits effectively. This ensures that the text remains within an acceptable range, regardless of the content’s length.

When using auto-sizing, it’s important to test your application on various devices and screen sizes to ensure that the text scales correctly across different resolutions. Emulators and physical devices can be used for this. Pay attention to how the text interacts with other UI elements and adjust the layout accordingly. Additionally, consider the impact of localization on auto-sizing. Text in different languages may have varying lengths, so it’s important to test your application with localized content to ensure that the auto-sizing behavior remains optimal.

Here are some key considerations for using Auto-fit TextView for Android effectively:

  • Set appropriate minimum and maximum text sizes to maintain readability.
  • Test your application on various devices and screen sizes.
  • Consider the impact of localization on text length.

Advanced Techniques and Use Cases

Beyond the basic implementation, there are several advanced techniques and use cases where Auto-fit TextView for Android can be particularly valuable. One such technique is combining auto-sizing with other TextView properties like maxLines to create more sophisticated text layouts. By limiting the number of lines, you can prevent the text from overflowing vertically while still ensuring that it fits horizontally. For example, consider a scenario where you want to display a short description of a product in a list item. By setting maxLines to 2 or 3 and enabling auto-sizing, you can ensure that the description always fits within the available space, regardless of its length, without truncating important information.

Another advanced use case is implementing custom auto-sizing behavior based on specific application requirements. For instance, you might want to adjust the text size based on the user’s font size preference or the device’s orientation. This can be achieved by programmatically controlling the auto-sizing parameters and dynamically updating them based on the desired conditions. This level of customization allows you to create highly adaptive and user-friendly applications that cater to individual user needs.

Consider the use case of creating a custom view that displays a numerical value with a corresponding unit. The value and the unit might have varying lengths, and you want to ensure that they always fit within the view’s bounds without overlapping. By using two Auto-fit TextView for Android elements, one for the value and one for the unit, you can ensure that both elements scale independently to fit the available space, creating a visually appealing and informative display. Proper use of the auto-fit functionality will greatly improve the user experience.

  • Combining auto-sizing with maxLines for sophisticated text layouts.
  • Implementing custom auto-sizing behavior based on application requirements.
Infographic showing before/after of Auto-fit TextView implementation
FAQ: Auto-fit TextView for Android ----------------------------------
What is Auto-fit TextView in Android?
Auto-fit TextView is a feature that automatically adjusts the text size of a TextView to fit within its bounds, preventing truncation and ensuring readability.
Which Android API levels support Auto-fit TextView?
Auto-fit TextView was introduced in Android API level 17 and significantly enhanced in API level 26 with support library backport.
How do I enable Auto-fit TextView in XML?
You can enable it by adding the app:autoSizeTextType attribute to your TextView in the layout file, setting it to "uniform" or "granularity".
Can I control the minimum and maximum text sizes for Auto-fit TextView?
Yes, you can use the app:autoSizeMinTextSize and app:autoSizeMaxTextSize attributes in XML or the corresponding methods in Java/Kotlin to set these limits.
How can I implement Auto-fit TextView programmatically?
Use the TextViewCompat class from the androidx.core.widget package and its methods like setAutoSizeTextTypeWithDefaults() or setAutoSizeTextTypeUniformWithConfiguration().
The power of **Auto-fit TextView for Android** lies in its ability to adapt seamlessly to varying content and screen sizes, ensuring your text always looks its best. But remember, thoughtful implementation is key. Setting appropriate size constraints and testing across different devices will help you harness the full potential of this feature. Don't just let your text overflow; take control and create a more polished, user-friendly experience. For further exploration, consider researching related topics like ConstraintLayout for flexible layouts or exploring advanced text styling options in Android. You can also review the official Android documentation on [TextView auto-sizing](https://developer.android.com/reference/android/widget/TextViewattr_android:autoSizeTextType), check out [this Medium article on auto-sizing TextViews](https://medium.com/@murashov.alex/autosizing-textview-on-android-e177295949c7) or investigate [Stack Overflow discussions on the topic](https://stackoverflow.com/questions/27439057/android-textview-autosizing). Ready to level up your Android UI development? Check out more tips and tricks at [our blog](https://courthousezoological.com/n7sqp6kh?key=e6dd02bc5dbf461b97a9da08df84d31c) for even more ways to enhance your Android applications.

Question & Answer :
Background

Many times we need to auto-fit the font of the TextView to the boundaries given to it.

The problem

Sadly, even though there are many threads and posts (and suggested solutions) talking about this problem (example here, here and here), none of them actually work well.

That’s why, I’ve decided to test each of them till I find the real deal.

I think that the requirements from such a textView should be:

  1. Should allow using any font, typeface, style, and set of characters.
  2. Should handle both width and height
  3. No truncation unless text cannot fit because of the limitation, we’ve given to it (example: too long text, too small available size). However, we could request for horizontal/vertical scrollbar if we wish, just for those cases.
  4. Should allow multi-line or single-line. In case of multi-line, allow max & min lines.
  5. Should not be slow in computation. Using a loop for finding the best size? At least optimize it and don’t increment your sampling by 1 each time.
  6. In case of multi-line, should allow to prefer resizing or using more lines, and/or allow to choose the lines ourselves by using the “\n” character.

What I’ve tried

I’ve tried so many samples (including those of the links, I’ve written about), and I’ve also tried to modify them to handle the cases, I’ve talked about, but none really work.

I’ve made a sample project that allows me to visually see if the TextView auto-fits correctly.

Currently, my sample project only randomize the text (the English alphabet plus digits) and the size of the textView, and let it stay with single line, but even this doesn’t work well on any of the samples I’ve tried.

Here’s the code (also available here):

File res/layout/activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:text="Button" /> <FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_above="@+id/button1" android:layout_alignParentLeft="true" android:background="#ffff0000" android:layout_alignParentRight="true" android:id="@+id/container" android:layout_alignParentTop="true" /> </RelativeLayout> 

File src/.../MainActivity.java

public class MainActivity extends Activity { private final Random _random =new Random(); private static final String ALLOWED_CHARACTERS ="qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890"; @Override protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final ViewGroup container=(ViewGroup)findViewById(R.id.container); findViewById(R.id.button1).setOnClickListener(new OnClickListener() { @Override public void onClick(final View v) { container.removeAllViews(); final int maxWidth=container.getWidth(); final int maxHeight=container.getHeight(); final FontFitTextView fontFitTextView=new FontFitTextView(MainActivity.this); final int width=_random.nextInt(maxWidth)+1; final int height=_random.nextInt(maxHeight)+1; fontFitTextView.setLayoutParams(new LayoutParams(width,height)); fontFitTextView.setSingleLine(); fontFitTextView.setBackgroundColor(0xff00ff00); final String text=getRandomText(); fontFitTextView.setText(text); container.addView(fontFitTextView); Log.d("DEBUG","width:"+width+" height:"+height+" text:"+text); } }); } private String getRandomText() { final int textLength=_random.nextInt(20)+1; final StringBuilder builder=new StringBuilder(); for(int i=0;i<textLength;++i) builder.append(ALLOWED_CHARACTERS.charAt(_random.nextInt(ALLOWED_CHARACTERS.length()))); return builder.toString(); } } 

The question

Does anybody know of a solution for this common problem that actually work?

Even a solution that has much less features that what I’ve written about, for example one that has just a constant number of lines of text, and adjusts its font according to its size, yet never have weird glitches and having the text get too large/small compared to its available space.


GitHub project

Since this is such an important TextView, I’ve decided to publish a library, so that everyone could easily use it, and contribute to it, here.

Thanks to MartinH’s simple fix here, this code also takes care of android:drawableLeft, android:drawableRight, android:drawableTop and android:drawableBottom tags.


My answer here should make you happy Auto Scale TextView Text to Fit within Bounds

I have modified your test case:

@Override protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final ViewGroup container = (ViewGroup) findViewById(R.id.container); findViewById(R.id.button1).setOnClickListener(new OnClickListener() { @Override public void onClick(final View v) { container.removeAllViews(); final int maxWidth = container.getWidth(); final int maxHeight = container.getHeight(); final AutoResizeTextView fontFitTextView = new AutoResizeTextView(MainActivity.this); final int width = _random.nextInt(maxWidth) + 1; final int height = _random.nextInt(maxHeight) + 1; fontFitTextView.setLayoutParams(new FrameLayout.LayoutParams( width, height)); int maxLines = _random.nextInt(4) + 1; fontFitTextView.setMaxLines(maxLines); fontFitTextView.setTextSize(500);// max size fontFitTextView.enableSizeCache(false); fontFitTextView.setBackgroundColor(0xff00ff00); final String text = getRandomText(); fontFitTextView.setText(text); container.addView(fontFitTextView); Log.d("DEBUG", "width:" + width + " height:" + height + " text:" + text + " maxLines:" + maxLines); } }); } 

I am posting code here at per android developer’s request:

Final effect:

Enter image description here

Sample Layout file:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:padding="16dp" > <com.vj.widgets.AutoResizeTextView android:layout_width="match_parent" android:layout_height="100dp" android:ellipsize="none" android:maxLines="2" android:text="Auto Resized Text, max 2 lines" android:textSize="100sp" /> <!-- maximum size --> <com.vj.widgets.AutoResizeTextView android:layout_width="match_parent" android:layout_height="100dp" android:ellipsize="none" android:gravity="center" android:maxLines="1" android:text="Auto Resized Text, max 1 line" android:textSize="100sp" /> <!-- maximum size --> <com.vj.widgets.AutoResizeTextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Auto Resized Text" android:textSize="500sp" /> <!-- maximum size --> </LinearLayout> 

And the Java code:

import android.annotation.TargetApi; import android.content.Context; import android.content.res.Resources; import android.graphics.RectF; import android.os.Build; import android.text.Layout.Alignment; import android.text.StaticLayout; import android.text.TextPaint; import android.util.AttributeSet; import android.util.SparseIntArray; import android.util.TypedValue; import android.widget.TextView; public class AutoResizeTextView extends TextView { private interface SizeTester { /** * * @param suggestedSize * Size of text to be tested * @param availableSpace * available space in which text must fit * @return an integer < 0 if after applying {@code suggestedSize} to * text, it takes less space than {@code availableSpace}, > 0 * otherwise */ public int onTestSize(int suggestedSize, RectF availableSpace); } private RectF mTextRect = new RectF(); private RectF mAvailableSpaceRect; private SparseIntArray mTextCachedSizes; private TextPaint mPaint; private float mMaxTextSize; private float mSpacingMult = 1.0f; private float mSpacingAdd = 0.0f; private float mMinTextSize = 20; private int mWidthLimit; private static final int NO_LINE_LIMIT = -1; private int mMaxLines; private boolean mEnableSizeCache = true; private boolean mInitializedDimens; public AutoResizeTextView(Context context) { super(context); initialize(); } public AutoResizeTextView(Context context, AttributeSet attrs) { super(context, attrs); initialize(); } public AutoResizeTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initialize(); } private void initialize() { mPaint = new TextPaint(getPaint()); mMaxTextSize = getTextSize(); mAvailableSpaceRect = new RectF(); mTextCachedSizes = new SparseIntArray(); if (mMaxLines == 0) { // no value was assigned during construction mMaxLines = NO_LINE_LIMIT; } } @Override public void setTextSize(float size) { mMaxTextSize = size; mTextCachedSizes.clear(); adjustTextSize(); } @Override public void setMaxLines(int maxlines) { super.setMaxLines(maxlines); mMaxLines = maxlines; adjustTextSize(); } public int getMaxLines() { return mMaxLines; } @Override public void setSingleLine() { super.setSingleLine(); mMaxLines = 1; adjustTextSize(); } @Override public void setSingleLine(boolean singleLine) { super.setSingleLine(singleLine); if (singleLine) { mMaxLines = 1; } else { mMaxLines = NO_LINE_LIMIT; } adjustTextSize(); } @Override public void setLines(int lines) { super.setLines(lines); mMaxLines = lines; adjustTextSize(); } @Override public void setTextSize(int unit, float size) { Context c = getContext(); Resources r; if (c == null) r = Resources.getSystem(); else r = c.getResources(); mMaxTextSize = TypedValue.applyDimension(unit, size, r.getDisplayMetrics()); mTextCachedSizes.clear(); adjustTextSize(); } @Override public void setLineSpacing(float add, float mult) { super.setLineSpacing(add, mult); mSpacingMult = mult; mSpacingAdd = add; } /** * Set the lower text size limit and invalidate the view * * @param minTextSize */ public void setMinTextSize(float minTextSize) { mMinTextSize = minTextSize; adjustTextSize(); } private void adjustTextSize() { if (!mInitializedDimens) { return; } int startSize = (int) mMinTextSize; int heightLimit = getMeasuredHeight() - getCompoundPaddingBottom() - getCompoundPaddingTop(); mWidthLimit = getMeasuredWidth() - getCompoundPaddingLeft() - getCompoundPaddingRight(); mAvailableSpaceRect.right = mWidthLimit; mAvailableSpaceRect.bottom = heightLimit; super.setTextSize( TypedValue.COMPLEX_UNIT_PX, efficientTextSizeSearch(startSize, (int) mMaxTextSize, mSizeTester, mAvailableSpaceRect)); } private final SizeTester mSizeTester = new SizeTester() { @TargetApi(Build.VERSION_CODES.JELLY_BEAN) @Override public int onTestSize(int suggestedSize, RectF availableSPace) { mPaint.setTextSize(suggestedSize); String text = getText().toString(); boolean singleline = getMaxLines() == 1; if (singleline) { mTextRect.bottom = mPaint.getFontSpacing(); mTextRect.right = mPaint.measureText(text); } else { StaticLayout layout = new StaticLayout(text, mPaint, mWidthLimit, Alignment.ALIGN_NORMAL, mSpacingMult, mSpacingAdd, true); // Return early if we have more lines if (getMaxLines() != NO_LINE_LIMIT && layout.getLineCount() > getMaxLines()) { return 1; } mTextRect.bottom = layout.getHeight(); int maxWidth = -1; for (int i = 0; i < layout.getLineCount(); i++) { if (maxWidth < layout.getLineWidth(i)) { maxWidth = (int) layout.getLineWidth(i); } } mTextRect.right = maxWidth; } mTextRect.offsetTo(0, 0); if (availableSPace.contains(mTextRect)) { // May be too small, don't worry we will find the best match return -1; } else { // too big return 1; } } }; /** * Enables or disables size caching, enabling it will improve performance * where you are animating a value inside TextView. This stores the font * size against getText().length() Be careful though while enabling it as 0 * takes more space than 1 on some fonts and so on. * * @param enable * Enable font size caching */ public void enableSizeCache(boolean enable) { mEnableSizeCache = enable; mTextCachedSizes.clear(); adjustTextSize(getText().toString()); } private int efficientTextSizeSearch(int start, int end, SizeTester sizeTester, RectF availableSpace) { if (!mEnableSizeCache) { return binarySearch(start, end, sizeTester, availableSpace); } int key = getText().toString().length(); int size = mTextCachedSizes.get(key); if (size != 0) { return size; } size = binarySearch(start, end, sizeTester, availableSpace); mTextCachedSizes.put(key, size); return size; } private static int binarySearch(int start, int end, SizeTester sizeTester, RectF availableSpace) { int lastBest = start; int lo = start; int hi = end - 1; int mid = 0; while (lo <= hi) { mid = (lo + hi) >>> 1; int midValCmp = sizeTester.onTestSize(mid, availableSpace); if (midValCmp < 0) { lastBest = lo; lo = mid + 1; } else if (midValCmp > 0) { hi = mid - 1; lastBest = hi; } else { return mid; } } // Make sure to return the last best. // This is what should always be returned. return lastBest; } @Override protected void onTextChanged(final CharSequence text, final int start, final int before, final int after) { super.onTextChanged(text, start, before, after); adjustTextSize(); } @Override protected void onSizeChanged(int width, int height, int oldwidth, int oldheight) { mInitializedDimens = true; mTextCachedSizes.clear(); super.onSizeChanged(width, height, oldwidth, oldheight); if (width != oldwidth || height != oldheight) { adjustTextSize(); } } } 

Warning:

Beware of this resolved bug in Android 3.1 (Honeycomb) though.