之前在项目中遇到了测量字符串手机显示的宽度与高度的问题,最近也遇到同样的问题,故将相关的知识点积累如下:
- 在View中draw一个字符串,如何获得字符串所占据的高度与宽度;
- 在宽度固定的TextView中,如何自动缩小字体来适配TextView,使之刚好在这个TextView中显示完全;
1.自定义View中获取字符串的高度宽度
比如我现在自定义了一个MyView,我现在想在这个MyView中显示一个字符串,同时我想获取这个字符串的所占据的高度和宽度,示例代码如下:
/**
* @ClassName: MyView
* @Description: TODO
* @author lixiasong
* @date 2016-8-4 下午2:59:19
*
*/
public class MyView extends View {
private Paint mPaint ;
/**
* @param context
* @param attrs
*/
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
init();
}
private void init()
{
//声明一个Paint
mPaint = new Paint();
//设置字体大小
mPaint.setTextSize(20.0f);
//用来测试的字符串
String testString = "test string";
/*
* 根据 getTextBounds获取宽度和高度
*/
Rect rec = new Rect();
mPaint.getTextBounds(testString, 0, testString.length(), rec);
//宽度
int width1 = rec.right - rec.left;
//高度
int height1 = rec.bottom - rec.top ;
/*
* 根据 measureText获取宽度
*/
float width2 = mPaint.measureText(testString);
}
}
对于方法getTextBounds与measureText均能够获取到字符串的宽度,区别的话如下,其中红色的线为getTextBounds所测宽高度,粉红色线为measureText所测宽高度:
2.字符串大小自适应固定宽度TextView
在某些情况下我们的TextView的大小是固定的,我们希望不论多长的字符串,都能够自动调整大小来适应我们的TextView,示例代码如下:
/**
*
* @ClassName: MainActivity
* @Description: TODO
* @author lixiasong
* @date 2016-8-4 下午3:19:17
*
*/
public class MainActivity extends Activity {
private TextView mTextView ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String testString = "this is a test string.";
mTextView = (TextView)findViewById(R.id.textview1);
//设置固定的宽高度
mTextView.setWidth(100);
mTextView.setHeight(300);
mTextView.setText(testString);
//设置计算好的字体大小
mTextView.setTextSize(getTextSize(mTextView, 100, testString));
}
public float getTextSize(TextView tv , int w, String str)
{
//字符最大的大小
float defaultSize = 40.0f;
for(;;)
{
mTextView.setTextSize(defaultSize);
Paint paint = mTextView.getPaint();
float wm = paint.measureText(str);
if(wm <= w)
break;
else
//每次减小的步长
defaultSize -= 0.1;
}
return defaultSize;
}
}
这里需要注意的有两点:
(1) 当TextView已经存在的时候,我们不能像1中那样重新声明一个Paint,而是获取该TextView的Paint,即mTextView.getPaint();
(2) 每次textSize减小的步长,步长越小适配的越精准,但是循环的次数越多,消耗的时间越多,多大的步长需要根据实际情况来权衡。
若有不当之处,还请大家指出,谢谢。
参考:Paint类measureText与getTextBounds的区别