我正在尝试创建一个方法来调整 TextView
中的多行文本的大小,使其适合 TextView
的边界(X和Y维度) .
目前,我有一些东西,但它只是调整文本的大小,使文本的第一个字母/字符填充 TextView
的尺寸(即只有第一个字母是可见的,而且它是巨大的) . 我需要它来适应TextView边界内的所有文本行 .
这是我到目前为止:
public static void autoScaleTextViewTextToHeight(TextView tv)
{
final float initSize = tv.getTextSize();
//get the width of the view's back image (unscaled)....
float minViewHeight;
if(tv.getBackground()!=null)
{
minViewHeight = tv.getBackground().getIntrinsicHeight();
}
else
{
minViewHeight = 10f;//some min.
}
final float maxViewHeight = tv.getHeight() - (tv.getPaddingBottom()+tv.getPaddingTop())-12;// -12 just to be sure
final String s = tv.getText().toString();
//System.out.println(""+tv.getPaddingTop()+"/"+tv.getPaddingBottom());
if(minViewHeight >0 && maxViewHeight >2)
{
Rect currentBounds = new Rect();
tv.getPaint().getTextBounds(s, 0, s.length(), currentBounds);
//System.out.println(""+initSize);
//System.out.println(""+maxViewHeight);
//System.out.println(""+(currentBounds.height()));
float resultingSize = 1;
while(currentBounds.height() < maxViewHeight)
{
resultingSize ++;
tv.setTextSize(resultingSize);
tv.getPaint().getTextBounds(s, 0, s.length(), currentBounds);
//System.out.println(""+(currentBounds.height()+tv.getPaddingBottom()+tv.getPaddingTop()));
//System.out.println("Resulting: "+resultingSize);
}
if(currentBounds.height()>=maxViewHeight)
{
//just to be sure, reduce the value
tv.setTextSize(resultingSize-1);
}
}
}
我认为问题在于使用 tv.getPaint().getTextBounds(...)
. 它总是返回文本边界的小数字...相对于 tv.getWidth()
和 tv.getHeight()
值的小...即使文本大小远远大于 TextView
的宽度或高度 .
14 回答
MavenCentral的AutofitTextView库很好地处理了这个问题 . 来源于Github(1k星)https://github.com/grantland/android-autofittextview
将以下内容添加到
app/build.gradle
在代码中启用任何View扩展TextView:
启用任何以XML格式扩展TextView的View:
在代码或XML中使用内置的Widget:
我能够使用以下代码回答我自己的问题(见下文),但我的解决方案非常特定于应用程序 . 例如,这可能只是看起来很好和/或适用于大小约为的TextView . 屏幕1/2(同时还有40px的上边距和20px的边距......没有底边距) .
但是,使用这种方法,您可以创建自己的类似实现 . 静态方法基本上只查看字符数并确定应用于TextView文本大小的缩放因子,然后逐渐增加文本大小,直到整体高度(估计高度 - 使用文本的宽度,文本高度和TextView的宽度刚好低于TextView的宽度 . 确定缩放因子所需的参数(即if / else if语句)是通过猜测和检查来设置的 . 您可能需要使用这些数字来使其适用于您的特定应用程序 .
这不是最优雅的解决方案,虽然它很容易编码,但它对我有用 . 有没有人有更好的方法?
谢谢 .
我有同样的问题,写了一个似乎适合我的课程 . 基本上,我使用静态布局在单独的画布中绘制文本并重新测量,直到找到适合的字体大小 . 您可以在下面的主题中看到该课程 . 我希望它有所帮助 .
Auto Scale TextView Text to Fit within Bounds
在我自己寻找解决方案的同时偶然发现了...我已经尝试了所有其他解决方案,我可以在堆栈溢出等上看到但是没有真正有效,所以我自己写了 .
基本上,通过将文本视图包装在自定义线性布局中,我已经能够通过确保以固定宽度进行测量来成功地正确测量文本 .
然后是线性布局代码
希望这有助于某人 .
我已经玩了很长一段时间,试图在各种7英寸平板电脑(点燃火,Nexus7,以及中国的一些廉价的低分辨率屏幕)和设备上使我的字体大小正确 .
最终对我有用的方法如下 . “32”是一个任意因子,基本上在7“平板电脑水平线上给出大约70个字符,这是我正在寻找的字体大小 . 相应地调整 .
New since Android O:
https://developer.android.com/preview/features/autosizing-textview.html
也许在尝试文本测量之前尝试将setHoriztonallyScrolling()设置为true,以便textView不会尝试在多行上布局文本
一种方法是为每个通用屏幕尺寸指定不同的sp尺寸 . 例如,为小屏幕提供8sp,为普通屏幕提供12sp,为大屏幕提供16sp,为xlarge提供20sp . 然后让你的布局引用@dimen text_size或其他任何你可以放心,因为密度是通过sp单位处理的 . 有关此方法的详细信息,请参阅以下链接 .
http://www.developer.android.com/guide/topics/resources/more-resources.html#Dimension
但是,我必须注意,支持更多语言意味着在测试阶段会有更多的工作,特别是如果你有兴趣将文本保存在一行上,因为有些语言有更长的单词 . 在这种情况下,例如,在values-de-large文件夹中创建一个dimens.xml文件,并手动调整该值 . 希望这可以帮助 .
这是我根据其他一些反馈创建的解决方案 . 此解决方案允许您以XML格式设置文本的大小,该大小将是最大大小,并且它将自行调整以适合视图高度 . Size Adjusting TextView
如果您唯一的要求是让文本自动拆分并在下一行继续,并且高度不重要那么就这样 .
这将根据您的maxEms值将TextView垂直包装到其内容中 .
检查我的解决方案是否有助于您
Auto Scale TextView Text to Fit within Bounds
我发现这对我来说效果很好 . 见:https://play.google.com/store/apps/details?id=au.id.rupert.chauffeurs_name_board&hl=en
源代码来自http://www.rupert.id.au/chauffeurs_name_board/verson2.php
http://catchthecows.com/?p=72和https://github.com/catchthecows/BigTextButton
这是基于mattmook的答案 . 它在某些设备上运行良好,但并非全部 . 我将调整大小移动到测量步骤,使最大字体大小成为自定义属性,考虑边距,并扩展FrameLayout而不是LineairLayout .
这在attrs.xml中:
最后像这样使用:
试试这个...