如何根据视图最大尺寸在多行TextView上自动调整文本大小?

nun*_*des 20 android word-wrap textview text-size typeface

我一直在寻找一种在textview中自动调整文本的方法.通过我的搜索,我找到了许多解决方案,如:

但和许多其他人一样,这些并不能解决我的问题.当我们使用带有多行的TextView时,它们无法按预期工作.

基本上我的目标是这个:

阶段1 阶段2 第3阶段 第4阶段

如您所见,文本根据宽度,高度调整大小,并注意换行,创建多行文本视图.也可以改变字体.

我解决这个问题的一个想法是这样的:

int size = CONSTANT_MAX_SIZE;
TextView tv = (TextView) findViewById(R.id.textview1)
while(Math.abs(tv.getMeasuredHeight()) >= TEXTVIEW_MAX_HEIGHT) {
    size--;
    tv.setTextSize(size);
    tv.measure(MeasureSpec.UNSPECIFIED,MeasureSpec.UNSPECIFIED);
    i++;
}
Run Code Online (Sandbox Code Playgroud)

CONSTANT_MAX_SIZE是一个常量,用于定义字体的最大大小(TextView中的textsize礼节)

TEXTVIEW_MAX_HEIGHT是一个常量,用于定义textview可以具有的最大大小.

每次textview中的文本发生更改时都会调用此方法.

textview xml是这样的:

<TextView
     android:id="@+id/textview1"
     android:layout_width="200dp"
     android:layout_height="wrap_content"
     android:singleLine="false"
     android:inputType="textMultiLine"
     android:text=""
     android:textSize="150sp" />
Run Code Online (Sandbox Code Playgroud)

由于宽度在XML中受到限制,因此只需要考虑视图的高度,因为调整它后android会在需要时自动创建多行.

虽然这是一个潜在的解决方案并不完美(远离它)并且它不支持调整大小(当您删除文本时).

任何sugestions和/或想法?

nun*_*des 17

当我等待这个问题的可能解决方案时,我一直在试验并试图找出它.

这个问题的最接近的解决方案是基于paint的方法.

基本上paint有一个叫做'breaktext'的方法,它有:

public int breakText(CharSequence text,int start,int end,boolean measureForwards,float maxWidth,float [] measuredWidth)

在API级别1中添加

测量文本,如果测量的宽度超过maxWidth,则提前停止.返回测量的字符数,如果measuredWidth不为null,则返回测量的实际宽度.

我将它与绘画'getTextBounds'结合起来:

public void getTextBounds(String text,int start,int end,Rect bounds)

在API级别1中添加

返回边界(由调用者分配)包含所有>字符的最小矩形,隐含原点为(0,0).

所以现在我可以获得适合给定宽度和那些字符高度的字符数.

使用一段时间,您可以继续从要测量的字符串移动删除字符并获取行数(通过使用while(index <string.length))并将其乘以getTextBounds中获得的高度.

此外,您必须为每两行代表行之间的空间添加一个可变高度(在getTextBounds中不计算).

作为示例代码,知道多行文本高度的函数是这样的:

public int getHeightOfMultiLineText(String text,int textSize, int maxWidth) {
    paint = new TextPaint();
    paint.setTextSize(textSize);
    int index = 0;
    int linecount = 0;
    while(index < text.length()) {
        index += paint.breakText(text,index,text.length,true,maxWidth,null);
        linecount++;
    }

    Rect bounds = new Rect();
    paint.getTextBounds("Yy", 0, 2, bounds);
    // obtain space between lines
    double lineSpacing = Math.max(0,((lineCount - 1) * bounds.height()*0.25)); 

    return (int)Math.floor(lineSpacing + lineCount * bounds.height());
Run Code Online (Sandbox Code Playgroud)

注意:maxWidth变量以像素为单位

然后你必须在一段时间内调用这个方法来确定该高度的最大字体大小.示例代码是:

textSize = 100;
int maxHeight = 50;
while(getHeightOfMultiLineText(text,textSize,maxWidth) > maxHeight)
  textSize--;
Run Code Online (Sandbox Code Playgroud)

不幸的是,这是我能够从上面的图像中获得方面的唯一方法(据我所知).

希望这对任何试图克服这一障碍的人都有帮助.