android:ems 属性详细分析
TextViewems 属性是干嘛的?我们先看一下官方的提供的方法注释/*** Sets the width of the TextView to be exactly {@code ems} wide.** This value is used for width calculation if LayoutParams does not force TextView to have an* ex
TextView ems 属性是干嘛的?我们先看一下官方的提供的方法注释
/**
* Sets the width of the TextView to be exactly {@code ems} wide.
*
* This value is used for width calculation if LayoutParams does not force TextView to have an
* exact width. Setting this value overrides previous minimum/maximum configurations such as
* {@link #setMinEms(int)} or {@link #setMaxEms(int)}.
*
* @param ems the exact width of the TextView in terms of ems
*
* @see #setWidth(int)
*
* @attr ref android.R.styleable#TextView_ems
*/
@android.view.RemotableViewMethod
public void setEms(int ems) {
mMaxWidth = mMinWidth = ems;
mMaxWidthMode = mMinWidthMode = EMS;
requestLayout();
invalidate();
}
大概是说:
将 TextView 的宽度设置为正好 {@code ems} 宽。
那ems代表什么意思呢?以 em 为单位的 TextView 的确切宽度。
额 。。 好像不是很明白😢
哼 找官方文档看看去
翻译如下:
使 TextView 正好有这么多 em 宽。
可以是整数值,例如“100”。
好吧 这个时候 可以手动去测一测。
<TextView
android:id="@+id/tv_ems"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:ellipsize="end"
android:ems="3"
android:text="@string/bt_ems"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
我们分别设置textview为汉字、英文以及英文加汉字对比看效果。
设置ems为 3
从上面的结果看,咦~这宽度不就是汉字的个数吗😻?但事情远远没有这么简单。我们在测试一下。
设置ems为 6
emm 这好像不是很对 配置的是6 但是竟然是7个汉字的长度🤢。。。。
设置ems为15
emm 有显示了17个汉字了。。。尴尬。好吧 没办法了 我们去看看源码这一块到底是怎么算宽度的吧!!!😡
首先看textview里面setEmx方法都干了 什么。
public void setEms(int ems) {
mMaxWidth = mMinWidth = ems;
mMaxWidthMode = mMinWidthMode = EMS;
}
设置了mMaxWidthMode 和mMinWidthMode 的模式为EMS。
将设置的ems值 传给了 mMaxWidth 和 mMinWidth 。
好接下来,接下来找计算宽度的方法,直接去onMeasure方法里面找。
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//其他代码省略
if (mMaxWidthMode == EMS) {
width = Math.min(width, mMaxWidth * getLineHeight());
} else {
width = Math.min(width, mMaxWidth);
}
if (mMinWidthMode == EMS) {
width = Math.max(width, mMinWidth * getLineHeight());
} else {
width = Math.max(width, mMinWidth);
}
//其他代码省略
}
我们找到了上面的一段代码,根据上面的分析。mMaxWidthMode = EMS。
所以,应该执行了 width = Math.min(width, mMaxWidth * getLineHeight());
而mMaxWidth = ems,所以 就变成了 ems*getLineHeight()。
那我们在看看getLineHeight做了什么吧!
/**
* Gets the vertical distance between lines of text, in pixels.
* Note that markup within the text can cause individual lines
* to be taller or shorter than this height, and the layout may
* contain additional first-or last-line padding.
* @return The height of one standard line in pixels.
*/
@InspectableProperty
public int getLineHeight() {
return FastMath.round(mTextPaint.getFontMetricsInt(null) * mSpacingMult + mSpacingAdd);
}
显而易见:获取文本行之间的垂直距离,以像素为单位。那不就是高度嘛!
所以破案了。最终的宽度就变成了,传入的ems*行高😯😯😯😯😯😯。
需要注意一点的是:🤦♀️将android:layout_width设置为match_parent和固定的宽度,ems是不生效的。
因为:onMeasure里面有这样的一段代码:
只有设置为wrap_content,才会走else的代码。
更多推荐
所有评论(0)