天天看點

Android 淺談 maxEms 屬性

      小菜最近調整一個小需求,為了整體顯示效果,需要限制一部分文字的長度,超過部分以...代替。

      小菜本想偷個懶,用 android:maxLength="6" 屬性配合 android:maxLines="1" 以及 android:ellipsize="end" 來實作,但是隻可限制字元床度為6,沒有省略号。然後想起有一個 android:maxEms="6" 屬性來實作,預設超過長度以省略号結束。結果發現并非按字元長度計算,小菜還是太天真了。

android:maxEms="6"

Tips1: android:singleLine="true" 屬性已經在 API 中不建議使用,小菜在現有的裝置中測試與 android:maxLines="1" 屬性效果完全一緻。

Tips2: 在使用 android:maxEms="6" 屬性時, TextView 的寬度需為 wrap_content 方式。

以下是小菜測試時遇到的問題:

左側是從 maxEms = “1” 開始遞增到 “16”,右側是測量文字所占的寬度:

純漢字

純字母

純數字

測試發現:

  1. 無論是文字還是字母或是數字,設定完 maxEms 之後,文字所占的寬度是一緻的,随着 maxEms 的遞增,文字的寬度也是相同幅度遞增的;
  2. 不管是文字還是字母或數字,都不是單純的按照字元個數來展示的,而是所占螢幕的寬度,是以并不是網上一些朋友說的顯示内容為 maxEms - 1 +”...“。
  3. 若限制字元串長度請嘗試 maxLength,若字号不變,限制文字所在螢幕寬度,可嘗試 maxEms。

TextView 源碼中 maxEms

/**
* Makes the TextView at most this many ems wide
*
* @attr ref android.R.styleable#TextView_maxEms
*/
@android.view.RemotableViewMethod
public void setMaxEms(int maxems) {
    mMaxWidth = maxems;
    mMaxWidthMode = EMS;
    requestLayout();
    invalidate();
}
           
/**
* @return the maximum width of the TextView, expressed in ems or -1 if the maximum width
* was set in pixels instead (using {@link #setMaxWidth(int)} or {@link #setWidth(int)}).
* 文本視圖的最大寬度,以EMS表示,或如果寬度為1,則表示最大寬度
* 設定為像素(使用{@ Link LyStMax寬度(int)}或{@ Link LyStSuffelt(int)})
* @see #setMaxEms(int)
* @see #setEms(int)
*
* @attr ref android.R.styleable#TextView_maxEms
*/
public int getMaxEms() {
    return mMaxWidthMode == EMS ? mMaxWidth : -1;
}
           

小菜查閱相關資料以及自己的了解是:

  1. em 是字型寬度的排版機關,16 點字型中的一個是 16 分;
  2. em 和 ex 單元取決于字型,并且對于文檔中的每個元素可能不同。em 隻是字型大小。在具有 2in 字型的元素中,1em 是以意味着 2in。在 em 中表示大小,例如邊距和填充,意味着它們與字型大小有關,并且如果使用者有大字型(例如,在大螢幕上)或小字型(例如,在手持裝置上),大小将成比例。
  3. 它是字母 M 在給定的英語字型大小中的寬度。是以 2em 是這個字型中字母 M 的兩倍。字型不同于英語,它是這個字型中最寬的字母寬度,這個寬度是不同的像素大小,然後是英語字型中的 M 的寬度大小,但是它仍然是 1EM。是以如果我用 12sp 的英文字型使用文本,1M 相對于這個 12sp 的英語字型,用意大利字型加上1。

測試主要代碼:

// xml 中 TextView
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:ellipsize="end"
    android:maxEms="6"
    android:maxLines="1"
    android:text="@string/test_str1" />
           
// Kotlin 擷取文字寬度
fun getTextViewWidth(tv: TextView): String {
    val spec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
    tv.measure(spec, spec)
    val measuredWidthTicketNum = tv.getMeasuredWidth()
    return measuredWidthTicketNum.toString()
}
           

      下面是小菜的公衆号,歡迎閑來吐槽~

小菜公衆号

繼續閱讀