我正在寻找一种最佳的方法来调整包装文本在一个TextView,使它将适合它的getHeight和getWidth界限。我不是简单地寻找一种方法来包装文本-我想确保它既包装,又足够小,完全适合在屏幕上。
我在StackOverflow上看到了一些需要自动调整大小的情况,但它们要么是非常特殊的情况下的hack解决方案,没有解决方案,或涉及重新绘制TextView递归直到它足够小(这是内存紧张,迫使用户观看文本收缩一步一步与每次递归)。
但我相信有人已经找到了一个很好的解决方案,它不涉及我正在做的事情:编写几个繁重的例程来解析和测量文本,调整文本的大小,然后重复,直到找到一个合适的小尺寸。
TextView使用什么例程来包装文本?难道这些不能用来预测文本是否足够小吗?
是否有一个最佳实践的方法来自动调整TextView的大小,以适应,包装,在它的getHeight和getWidth边界?
警告,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小部件中,但我希望将修复代码保留在外部。
这是一个简单的解决方案,使用TextView本身和textchangedlistens添加到它:
expressionView = (TextView) findViewById(R.id.expressionView);
expressionView.addTextChangedListener(textAutoResizeWatcher(expressionView, 25, 55));
private TextWatcher textAutoResizeWatcher(final TextView view, final int MIN_SP, final int MAX_SP) {
return new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
@Override
public void afterTextChanged(Editable editable) {
final int widthLimitPixels = view.getWidth() - view.getPaddingRight() - view.getPaddingLeft();
Paint paint = new Paint();
float fontSizeSP = pixelsToSp(view.getTextSize());
paint.setTextSize(spToPixels(fontSizeSP));
String viewText = view.getText().toString();
float widthPixels = paint.measureText(viewText);
// Increase font size if necessary.
if (widthPixels < widthLimitPixels){
while (widthPixels < widthLimitPixels && fontSizeSP <= MAX_SP){
++fontSizeSP;
paint.setTextSize(spToPixels(fontSizeSP));
widthPixels = paint.measureText(viewText);
}
--fontSizeSP;
}
// Decrease font size if necessary.
else {
while (widthPixels > widthLimitPixels || fontSizeSP > MAX_SP) {
if (fontSizeSP < MIN_SP) {
fontSizeSP = MIN_SP;
break;
}
--fontSizeSP;
paint.setTextSize(spToPixels(fontSizeSP));
widthPixels = paint.measureText(viewText);
}
}
view.setTextSize(fontSizeSP);
}
};
}
private float pixelsToSp(float px) {
float scaledDensity = getResources().getDisplayMetrics().scaledDensity;
return px/scaledDensity;
}
private float spToPixels(float sp) {
float scaledDensity = getResources().getDisplayMetrics().scaledDensity;
return sp * scaledDensity;
}
这种方法将根据需要增加或减少字体大小以适应文本,尊重作为参数接收的MIN_SP和MAX_SP边界。
我刚刚创建了以下方法(基于Chase的想法),如果你想在任何画布上绘制文本,它可能会帮助你:
private static void drawText(Canvas canvas, int xStart, int yStart,
int xWidth, int yHeigth, String textToDisplay,
TextPaint paintToUse, float startTextSizeInPixels,
float stepSizeForTextSizeSteps) {
// Text view line spacing multiplier
float mSpacingMult = 1.0f;
// Text view additional line spacing
float mSpacingAdd = 0.0f;
StaticLayout l = null;
do {
paintToUse.setTextSize(startTextSizeInPixels);
startTextSizeInPixels -= stepSizeForTextSizeSteps;
l = new StaticLayout(textToDisplay, paintToUse, xWidth,
Alignment.ALIGN_NORMAL, mSpacingMult, mSpacingAdd, true);
} while (l.getHeight() > yHeigth);
int textCenterX = xStart + (xWidth / 2);
int textCenterY = (yHeigth - l.getHeight()) / 2;
canvas.save();
canvas.translate(textCenterX, textCenterY);
l.draw(canvas);
canvas.restore();
}
这可以在任何自定义视图的任何onDraw()方法中使用。