Android 如何根据视图最大尺寸自动调整多行文本视图上的文本大小?
我一直在寻找一种在文本视图中自动调整文本的方法。通过搜索,我找到了许多解决方案,如:Android 如何根据视图最大尺寸自动调整多行文本视图上的文本大小?,android,textview,word-wrap,typeface,text-size,Android,Textview,Word Wrap,Typeface,Text Size,我一直在寻找一种在文本视图中自动调整文本的方法。通过搜索,我找到了许多解决方案,如: 但和其他许多人一样,这些并不能解决我的问题。 当我们使用带有多行的TextView时,它们不能按预期工作 基本上,我的目标是: 如您所见,文本根据宽度、高度调整大小,并注意换行,从而创建多行文本视图。还可以更改字体 我解决这个问题的一个想法是: int size = CONSTANT_MAX_SIZE; TextView tv = (TextView) findViewById(R.id.text
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++;
}
<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" />
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());
常量\u MAX\u SIZE是定义字体最大大小的常量(TextView中的textsize property)
TEXTVIEW_MAX_HEIGHT是一个常量,用于定义TEXTVIEW可以具有的最大大小
每次更改textview中的文本时都会调用此函数
textview xml是这样的:
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++;
}
<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" />
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());
由于XML中的宽度会受到限制,因此只需要考虑视图的高度,因为在需要时调整视图会自动创建多行
虽然这是一个潜在的解决方案,但它的工作并不完美(远远不是),并且它不支持向下调整大小(当您删除文本时)
有什么建议和/或想法吗?当我等待这个问题的可能解决方案时,我一直在尝试并试图找出答案 这个问题最接近的解决方案是基于paint的方法 基本上,paint有一个名为“breaktext”的方法,该方法: 公共int-breakText(字符序列文本、int-start、int-end、布尔值 测量向前,浮点最大宽度,浮点[]测量宽度) 在API级别1中添加 测量文本,如果测量的宽度超过 最大宽度。返回已测量的字符数,如果 measuredWidth不为空,请在其中返回实际测量的宽度 我将其与绘画“getTextBounds”相结合,其中: public void getTextBounds(字符串文本、int-start、int-end、Rect-bounds) 在API级别1中添加 在边界内返回(由调用方分配)包含所有>字符的最小矩形,其隐含原点为(0,0) 现在我可以得到适合给定宽度的字符数和这些字符的高度 使用while,您可以继续移动要测量的字符串中的删除字符,并获得行数(使用while(index
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++;
}
<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" />
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());
不幸的是,就我所知,这是我从上面的图片中获得这一方面的唯一方法
希望这能对任何试图克服这一障碍的人有所帮助。你在这个问题上有一个很好的解决方案,但我从不同的角度看了这个问题。我认为这种逻辑更简单,更容易理解,至少对于新的android开发者来说是这样。 该思想的基础是在大字符串的空格之间插入“\n”字符。然后,我将textView中编辑的字符串设置为显示文本。 下面是代码
private String insertNewLineCharAtString(String str, int step){
StringBuilder sb = new StringBuilder();
int spaceCounter = 0;
String[] strArray = str.split(" ");
for(int i = 0; i < strArray.length; i++){
if(spaceCounter == step){
sb.append('\n');
sb.append(strArray[i]);
spaceCounter = 0;
}else{
sb.append(" "+strArray[i]);
}
spaceCounter++;
}
return sb.toString();
}
希望这能帮助你们中的许多人,让你们不想深入了解TextPaint、Rects和math函数。可编译的、已修复的代码:复制粘贴此代码,而不是已接受的代码,因为您需要修复它:)
谢谢你的解决方案,你是超人!我已经在TextView的派生类中实现了您的代码。该代码被转换为Xamarin android的C#代码。如果需要,您可以轻松地转换为Java(删除Java的第一个构造函数)
公共类AutoFitTextView:TextView
{
公共AutoFitTextView(System.IntPtr javaReference,Android.Runtime.jnihandle所有权转移)
:base(javaReference,transfer)
{
}
公共AutoFitTextView(上下文)
:基本(上下文)
{
}
公共AutoFitTextView(上下文上下文,IAttributeSet属性)
:base(上下文、属性)
{
}
公共void ResizeFontSize()
{
int textSize=50;
int maxHeight=这个.Height;
while(GetHeightOfMultiLineText(this.Text、textSize、this.Width)>maxHeight)
{
文本大小--;
}
float scaleFactor=Context.Resources.DisplayMetrics.ScaledDensity;
浮动附加系数=1.2f;
TextSize=((浮点)(TextSize/(additionalFactor*scaleFactor));
}
私有int GetHeightOfMultiLineText(字符串文本、int textSize、int maxWidth)
{
TextPaint paint=新的TextPaint();
paint.TextSize=TextSize;
int指数=0;
int lineCount=0;
while(索引
下面是AXML代码
<touchtest.AutoFitTextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/tvLabel2"
android:singleLine="false"
android:inputType="textMultiLine"
android:text="I am here To test this text" />
使用,我编写了一个TextView派生类,它可以自动调整文本大小并支持多行
import android.content.Context;
import android.os.Handler;
import android.text.Layout;
import android.text.TextPaint;
import android.text.TextUtils.TruncateAt;
import android.util.AttributeSet;
import android.util.TypedValue;
public class AutoResizeTextView extends TextView {
private Handler measureHandler = new Handler();
private Runnable requestLayout = new Runnable() {
@Override
public void run() {
requestLayout();
}
};
public AutoResizeTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public AutoResizeTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AutoResizeTextView(Context context) {
super(context);
}
@Override
protected void onMeasure(final int widthMeasureSpec,
final int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
final float maxWidth = getWidth();
final float maxHeight = getHeight();
if (maxWidth < 1.0f || maxHeight < 1.0f) {
return;
}
int index = 0;
int lineCount = 0;
CharSequence text = getText();
final TextPaint paint = getPaint();
while (index < text.length()) {
index += paint.breakText(text, index, text.length(), true, maxWidth, null);
lineCount++;
}
final float height = lineCount * getLineHeight() + (lineCount > 0 ?
(lineCount - 1) * paint.getFontSpacing() : 0);
if (height > maxHeight) {
final float textSize = getTextSize();
setTextSize(TypedValue.COMPLEX_UNIT_PX, (textSize - 1));
measureHandler.post(requestLayout);
}
}
}
导入android.content.Context;
导入android.os.Handler;
导入android.text.Layout;
导入android.text.TextPaint;
导入android.text.TextUtils.TruncateAt;
导入android.util.AttributeSet;
导入android.util.TypedValue;
公共类AutoResizeTextView扩展了TextView{
私有处理程序measureHandler=新处理程序();
private Runnable requestLayout=new Runnable(){