16

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?

Josh Hansen
  • 1,408
  • 2
  • 17
  • 20
  • First of all replace the ConstraintLayout with a FrameLayout and check if it at least behaves as expected then. Start with simple conditions and add variables if it works. – Eugen Pechanec Mar 13 '18 at 22:53

4 Answers4

12

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.

rjr-apps
  • 352
  • 4
  • 13
  • 1
    About the "internal padding" here is an article describing with precision all the different dimension surrounding and including the text: https://proandroiddev.com/android-and-typography-101-5f06722dd611 – Pierre-Olivier Dybman Sep 20 '18 at 20:06
  • If I get it right your code measures the width of a text string in a textView and sets the width of the textView to the measured width. So it's a workaround for `autoSize` + `wrap_content`. What I want is to measure the width of each word in a text string in a textView and get the maximum width. Then if the maximum width is larger than already set textView width, decrease textSize (or use autoSize) so that the longest word doesn't split. Height should be `wrap_content`. Does it relates to your answer? I can ask a new question if necessary. – Irfan Latif Apr 07 '20 at 07:57
3

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

Raimo
  • 1,494
  • 1
  • 10
  • 19
0

It sounds like you want the display ratio of the text to change, for the text to act akin to scaleXY for an ImageView. Autosize does not do that. Rasterizing and scaling up is a bad approach as it will result in half-pixels. You could rasterize at the desired width and then squash the height, scaling the height down to minimise the distortion.

straya
  • 5,002
  • 1
  • 28
  • 35
-4

You can try this

<TextView
android:id="@+id/vName"
android:layout_width="56dp"
android:layout_height="wrap_content"
android:maxLines="1"
android:text="Groupa"
app:autoSizeMinTextSize="12sp"
app:autoSizeMaxTextSize="20sp"
app:autoSizeTextType="uniform"
/>