private void autoFixTextView(TextView textView){
// 获取textview内宽度
int targetWidth = textView.getWidth() - textView.getPaddingLeft() - textView.getPaddingRight();
if (targetWidth <= 0) {
return;
}
// 这里主要是要用TextPaint里的getTextSize(),和measureText()方法,模拟不同textSize下textView的情况
TextPaint textPaint = new TextPaint(textView.getPaint());
//最大值
float hi = textPaint.getTextSize();
//最小值
float lo = 2;
// 设置精度
final float threshold = 0.5f;
// 二分法计算相对精度下合适的textSize 用以减少循环次数
while ((hi - lo) > threshold) {
float trySize = (hi + lo) / 2;
textPaint.setTextSize(trySize);
// 利用Paint内的measureText方法计算出text宽度
if (textPaint.measureText(textView.getText().toString()) >= targetWidth) {
hi = trySize; // too big
} else if (textPaint.measureText(textView.getText().toString()) < targetWidth) {
lo = trySize; // too small
}
}
// 用相对小的值避免大那么一丢丢导致悲剧
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, lo);
}
这样就可以让TextView适应你设置的宽度了,但是实际运用中你会发现textView.getWidth()取到的值为0,原因是在onCreate方法中控件还没有计算自己的参数所以没法取到所以这个方法推荐这么写:
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
autoFixTextView(textView);
}
在该回调中是可以取到值的。
当然你也可以重写一个TextView在onMeasure,onTextChanged以及onSizeChanged方法中调用该方法也可以实现相同的效果
重写的TextView我也贴上吧
public class AutoSizeTextView extends TextView {
private Paint mTestPaint;
public AutoSizeTextView(Context context) {
super(context);
initialise();
}
public AutoSizeTextView(Context context, AttributeSet attrs) {
super(context, attrs);
initialise();
}
private void initialise() {
mTestPaint = new Paint();
mTestPaint.set(this.getPaint());
//max size defaults to the initially specified text size unless it is too small
}
/* Re size the font so the specified text fits in the text box
* assuming the text box is the specified width.
*/
private void refitText(String text, int textWidth) {
if (textWidth <= 0)
return;
int targetWidth = textWidth - this.getPaddingLeft() - this.getPaddingRight();
float hi = 100;
float lo = 2;
// 相当于精度
final float threshold = 0.5f;
mTestPaint.set(this.getPaint());
while ((hi - lo) > threshold) {
// 二分法计算最接近精度的值
float size = (hi + lo) / 2;
mTestPaint.setTextSize(size);
// 利用Paint内的measureText方法计算出text宽度
if (mTestPaint.measureText(text) >= targetWidth ) {
hi = size; // too big
} else if (mTestPaint.measureText(text) < targetWidth) {
lo = size; // too small
}
}
// 用小值避免大那么一丢丢导致悲剧
this.setTextSize(TypedValue.COMPLEX_UNIT_PX, lo);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int height = getMeasuredHeight();
refitText(this.getText().toString(), parentWidth);
this.setMeasuredDimension(parentWidth, height);
}
@Override
protected void onTextChanged(final CharSequence text, final int start, final int before, final int after) {
refitText(text.toString(), this.getWidth());
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
if (w != oldw) {
refitText(this.getText().toString(), w);
}
}
}
网友评论