Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to `wrap_content` while autosizing an Android TextView?

Consider this layout:

<?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">
    <TextView
        android:id="@+id/textView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:autoSizeTextType="uniform"
        android:gravity="center"
        android:maxLines="1"
        android:text="TextView"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHeight_max="50dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.ConstraintLayout>

Because of the height_max constraint this leads to a TextView where the text fills the vertical space but there's a lot of horizontal padding inside of the TextView:

autosized TextView

What I want is for the width of that TextView to be set such that it matches the width of the autosized text content. But when I set android:layout_width="wrap_content" the width gets set based on the non-autosized text content:

non-autosized TextView

Is there any way to get the best of both worlds---have the text autosize based on a known height, and then set the width based on the width of the autosized text?

like image 844
Josh Hansen Avatar asked Mar 13 '18 22:03

Josh Hansen


2 Answers

Google's developer documentation specifically recommends against using wrap_content with autosized TextViews:

Note: If you set autosizing in an XML file, it is not recommended to use the value "wrap_content" for the layout_width or layout_height attributes of a TextView. It may produce unexpected results.

If you simply want your text to have a height of 50dp instead of 50sp, you could set the textSize to 50dp. But I suspect your goal is to have a textView that will autosize the text smaller based on layout constraints, and that solution won't do the job.

If you really can't have the extra horizontal space on your TextView from using a width of match_parent or 0dp, you could try programmatically setting the textview width layout parameter based on measuring the text with a TextPaint after the layout is created:

textView.post(new Runnable() {
    @Override
    public void run() {
        TextPaint textPaint = new TextPaint();
        textPaint.setTextSize(textView.getTextSize());

        float width = textPaint.measureText(textView.getText().toString());

        ViewGroup.LayoutParams layoutParams = textView.getLayoutParams();
        layoutParams.width = (int)width;
        textView.setLayoutParams(layoutParams);
    }
});

Keep in mind that if you go this route, you'll probably want to add some left and right padding to it. TextViews have a sort of internal padding, even if you set their padding to zero - but that gets overridden when the width parameter is set directly.

like image 121
rjr-apps Avatar answered Sep 19 '22 12:09

rjr-apps


Try using 0dp (which equals MATCH_CONSTRAINT) for the android:layout_width attribute of the TextView.

like image 38
Raimo Avatar answered Sep 21 '22 12:09

Raimo