我正在寻找一种最佳的方法来调整包装文本在一个TextView,使它将适合它的getHeight和getWidth界限。我不是简单地寻找一种方法来包装文本-我想确保它既包装,又足够小,完全适合在屏幕上。
我在StackOverflow上看到了一些需要自动调整大小的情况,但它们要么是非常特殊的情况下的hack解决方案,没有解决方案,或涉及重新绘制TextView递归直到它足够小(这是内存紧张,迫使用户观看文本收缩一步一步与每次递归)。
但我相信有人已经找到了一个很好的解决方案,它不涉及我正在做的事情:编写几个繁重的例程来解析和测量文本,调整文本的大小,然后重复,直到找到一个合适的小尺寸。
TextView使用什么例程来包装文本?难道这些不能用来预测文本是否足够小吗?
是否有一个最佳实践的方法来自动调整TextView的大小,以适应,包装,在它的getHeight和getWidth边界?
这里还有另一个解决方案,只是为了好玩。它可能不是很有效,但它确实处理了文本的高度和宽度,以及有标记的文本。
@Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec)
{
if ((MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.UNSPECIFIED)
&& (MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.UNSPECIFIED)) {
final float desiredWidth = MeasureSpec.getSize(widthMeasureSpec);
final float desiredHeight = MeasureSpec.getSize(heightMeasureSpec);
float textSize = getTextSize();
float lastScale = Float.NEGATIVE_INFINITY;
while (textSize > MINIMUM_AUTO_TEXT_SIZE_PX) {
// Measure how big the textview would like to be with the current text size.
super.onMeasure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
// Calculate how much we'd need to scale it to fit the desired size, and
// apply that scaling to the text size as an estimate of what we need.
final float widthScale = desiredWidth / getMeasuredWidth();
final float heightScale = desiredHeight / getMeasuredHeight();
final float scale = Math.min(widthScale, heightScale);
// If we don't need to shrink the text, or we don't seem to be converging, we're done.
if ((scale >= 1f) || (scale <= lastScale)) {
break;
}
// Shrink the text size and keep trying.
textSize = Math.max((float) Math.floor(scale * textSize), MINIMUM_AUTO_TEXT_SIZE_PX);
setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
lastScale = scale;
}
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
问题是关于如何在Button上有这个功能;对于TextView来说,它很容易,并且通过遵循这里的官方文档可以很好地工作。
Style.xml:
<style name="Widget.Button.CustomStyle" parent="Widget.MaterialComponents.Button">
<item name="android:minHeight">50dp</item>
<item name="android:maxWidth">300dp</item>
<item name="android:textStyle">bold</item>
<item name="android:textSize">16sp</item>
<item name="backgroundTint">@color/white</item>
<item name="cornerRadius">25dp</item>
<item name="autoSizeTextType">uniform</item>
<item name="autoSizeMinTextSize">10sp</item>
<item name="autoSizeMaxTextSize">16sp</item>
<item name="autoSizeStepGranularity">2sp</item>
<item name="android:maxLines">1</item>
<item name="android:textColor">@color/colorPrimary</item>
<item name="android:insetTop">0dp</item>
<item name="android:insetBottom">0dp</item>
<item name="android:lineSpacingExtra">4sp</item>
<item name="android:gravity">center</item>
</style>
用法:
<com.google.android.material.button.MaterialButton
android:id="@+id/blah"
style="@style/Widget.Button.CustomStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:text="Your long text, to the infinity and beyond!!! Why not :)" />
结果:
警告,Android蜂巢和冰淇淋三明治有bug
android版本:3.1 - 4.04有一个错误,setTextSize()内部的TextView只工作第一次(第一次调用)。
Bug描述如下:http://code.google.com/p/android/issues/detail?id=22493 http://code.google.com/p/android/issues/detail?id=17343#c9
解决方法是添加新的行字符文本分配给TextView之前改变大小:
final String DOUBLE_BYTE_SPACE = "\u3000";
textView.append(DOUBLE_BYTE_SPACE);
我在我的代码中使用它如下:
final String DOUBLE_BYTE_SPACE = "\u3000";
AutoResizeTextView textView = (AutoResizeTextView) view.findViewById(R.id.aTextView);
String fixString = "";
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB_MR1
&& android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
fixString = DOUBLE_BYTE_SPACE;
}
textView.setText(fixString + "The text" + fixString);
我将这个“\u3000”字符添加到文本的左侧和右侧,以保持文本居中。如果你把它对齐到左边,那么只追加到右边。当然,它也可以嵌入到AutoResizeTextView小部件中,但我希望将修复代码保留在外部。