如何在Android中根据文本长度动态自适应调整TextView的大小?

25
8个回答

25

16

以下是一种使用支持库的方法:

<androidx.appcompat.widget.AppCompatTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        android:breakStrategy="balanced" 
        android:gravity="center_horizontal"
        android:maxLines="1"
        android:text="Hello world" 
        android:textSize="300sp" 
        app:autoSizeTextType="uniform"
        tools:targetApi="o"/>
android:breakStrategy属性允许文本在换行时更好地排版,而不是默认情况下可能会断开单词的行为。

在gradle中,请使用以下代码:

implementation 'androidx.appcompat:appcompat:1.0.0-beta01'
implementation 'com.google.android.material:material:1.0.0-beta01'

或者这个:

implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:design:28.0.0'

请注意,建议在TextView上设置布局限制(宽度和/或高度),以确保您能够得到正确的结果。一切都取决于您的使用情况。


1
不建议使用autosize + wrap_content,可能会产生意想不到的结果:https://developer.android.com/guide/topics/ui/look-and-feel/autosizing-textview.html - Kikiwa
@Kikiwa 有道理。这只是一个例子。您应该始终具有某种自动调整大小规则,以便它知道如何自动调整大小。一切都取决于此TextView存在的布局。 - android developer
1
https://android.jlelse.eu/auto-sizing-textviews-in-android-d615ee2dc794 - Narendra

10

Support Library的修订版26.0.1为AppCompatTextView添加了文字自动缩放支持。

开发者现在可以让文本的大小根据TextView的大小和特性自动扩展或收缩,从而更容易地优化不同屏幕上或具有动态内容的文本大小。

粒度

在Java中:

调用setAutoSizeTextTypeUniformWithConfiguration()方法:

setAutoSizeTextTypeUniformWithConfiguration(int autoSizeMinTextSize, int autoSizeMaxTextSize, int autoSizeStepGranularity, int unit)

在XML中:

使用autoSizeMinTextSize、autoSizeMaxTextSize和autoSizeStepGranularity属性来设置布局XML文件中的自适应尺寸:

<android.support.v7.widget.AppCompatTextView
        android:id="@+id/autosizing_textview_presetsize" 
        android:layout_width="wrap_content" 
        android:layout_height="250dp" 
        android:layout_marginLeft="0dp" 
        android:layout_marginTop="0dp" 
        app:autoSizeMaxTextSize="100sp" 
        app:autoSizeMinTextSize="12sp" 
        app:autoSizeStepGranularity="2sp" 
        app:autoSizeText="uniform" 
        android:text="Hello World!" 
        android:textSize="100sp" 
        app:layout_constraintLeft_toLeftOf="parent" 
        app:layout_constraintTop_toTopOf="parent" />

预设大小

在Java中:

调用setAutoSizeTextTypeUniformWithPresetSizes()方法:

setAutoSizeTextTypeUniformWithPresetSizes(int[] presetSizes, int unit)

在XML中:

在布局的XML文件中使用autoSizePresetSizes属性:

<android.support.v7.widget.AppCompatTextView 
        android:id="@+id/autosizing_textview_presetsize" 
        android:layout_width="wrap_content" 
        android:layout_height="250dp" 
        android:layout_marginLeft="0dp" 
        android:layout_marginTop="0dp" 
        app:autoSizeText="uniform" 
        app:autoSizePresetSizes="@array/autosize_text_sizes" 
        android:text="Hello World!" 
        android:textSize="100sp" 
        app:layout_constraintLeft_toLeftOf="parent" 
        app:layout_constraintTop_toTopOf="parent" />

要将数组作为资源访问,请在 res/values/arrays.xml 文件中定义数组:

<array name="autosize_text_sizes">
    <item>10sp</item>
    <item>12sp</item>
    <item>20sp</item>
    <item>40sp</item>
    <item>100sp</item>
</array>

1
虽然文档很少,但对于setAutoSizeTextTypeUniformWithConfiguration的+1,列出的参数是有帮助的。其中unit是TypedValue常量之一,例如.COMPLEX_UNIT_SP或其他。 - josh527

5

addTextChangedListener是一个EditText的监听器。该监听器会监视EditText的更改,并且有三种不同的状态。

EditText edt = someEditText;
edt.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        }

        /*watch the editText on every input and changes, then mange the size by if statements and editText length*/
        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            if (edt.getText().toString().length() > 10){
                edt.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSizeSmall);
            }
            else if (edt.getText().toString().length() > 5){
                edt.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSizeMedium);
            }
        }

        @Override
        public void afterTextChanged(Editable s) {
        }
    });

更新:根据您的问题,您可以创建一个组件(自定义视图)并将其命名为AppCompatTextView, 在初始化时,您可以添加以下代码:

public class CustomTextView extends AppCompatTextView {
Context ctx;

public CustomTextView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    ctx = context;
    init();
}

public CustomTextView(Context context, AttributeSet attrs) {
    super(context, attrs);
    ctx = context;
    init();
}

public CustomTextView(Context context) {
    super(context);
    ctx = context;
    init();
}

public void init() {
    setOnTouchListener(null);
    addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            if (getText().toString().length() > 10){
                setTextSize(TypedValue.COMPLEX_UNIT_SP, textSizeSmall);
            }
            else if (getText().toString().length() > 5){
                setTextSize(TypedValue.COMPLEX_UNIT_SP, textSizeMedium);
            }
        }

        @Override
        public void afterTextChanged(Editable s) {

        }
    });
}

你必须在XML中使用它,而不是通常的textView


请在您的回答中增加更多的解释。 - Ivan Barayev
@IvanBarayev,请检查更新。 - Payam Kokabi
非常感谢。 - Ivan Barayev
我需要 TextView 而不是 EditView。 - Jobin Lawrance

0

使用下面的库非常适合您的需求。

根据文档:自动调整文本大小以完美地适应其边界的TextView。

链接:Android autofit textview


0

也许你可以尝试这样做:

EditText et = someEditText;
String text = et.getText().toString();
int textLength = text.length();

if (textLength > 25) {
    et.setTextSize(toSomeNumber as the size of the text);
} else if (textLength > 15) {
     et.setTextSize(toSomeNumber bigger than the previous);
} else {
      et.setTextSize(toSomeNumber this is the biggest);
}

更新: 如果您想以更Android的方式解决问题,可以参考这个问题。如何动态设置不同屏幕上TextView的文本大小

这是我在自己的代码中使用的方法。欢迎提出任何建议来增强我的代码。希望能帮到您。


有没有办法在布局本身中完成它? - Jobin Lawrance

0
也许其他解决方案都很好,但当文本溢出时减小字体大小是唯一适用于我的解决方案。
val txt = "Hello World"

textView.text = txt
textView.post {
    val isEllipsize: Boolean = it.layout.text.toString() != txt
    textView.setTextSize(
           TypedValue.COMPLEX_UNIT_SP,
           if (isEllipsize) 12f else 14f
     )
}

-1
请注意,这会破坏可访问性。例如,如果用户通过手机设置决定更改字体大小,因为他看不清楚,高度设置为DP的自动调整文本视图将不受影响。
为了解决这个问题,您应该使用带有SP的android:layout_height,这样当可访问性设置更改时,它也会被缩放。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接