Android字串處理-emoji
一、名詞解釋
一個完整的Unicode字元叫程式碼點/CodePoint,而一個Java char 叫程式碼單元code unit;
程式碼點,是從Unicode標準而來的術語,Unicode標準的核心是一個編碼字符集, 它為每一個字元分配一個唯一數字。Unicode標準始終使用16進位制數字,並且在書寫時在前面加上U+, 如字元“A”的編碼為“U+0041”。
程式碼點是指可用於編碼字符集的數字。編碼字符集定義一個有效的程式碼點範圍, 但是並不一定將字元分配給所有這些程式碼點。有效的Unicode程式碼點範圍是U+0000至U+10FFFF。 Unicode4.0將字元分配給一百多萬個程式碼點中的96382個程式碼點。
string物件以UTF-16儲存Unicode字元,需要用2個字元表示一個超大字符集漢字,這種表示方式為 Sruuogate,第一個字元叫Surrogate High,第二個就是Surrogate Low 判斷一個char是否是Surrogate區的字元,用Character的isHighSurrogate()/isLowSurrogate()方法。 從兩個Surrogate High/Low字元,返回一個完整的Unicode CodePoint用Character.toCodePoint()/codePointAt() 一個Code Point,可能需要一個也可能需要兩個char表示,因此不能直接使用CharSequence.length() 方法返回一個字串到底有多少個漢字,而需要用String.codePointCount()/Character.codePointCount()。
二、CodePonits使用
要定位字串中的第N個字元,不能直接將n作為偏移量,而需要從字串頭部依次遍歷得到,需要 String.offsetByCodePoints()。
從字串的當前字元,找到上一個字元,不能直接用offset實現,而需要 String.codePointBefore(),或String.offsetByCodePoints() 。
從當前字元,找下一個字元,需要判斷當前CodePoint的長度,再計算得到 String.offsetByCodePoints()。
codePoint在Textview擷取字串(尤其是emoji表情)時特別有用,
public String ellipsizeText(TextView textView, String text) { String tmpTxt = null; if (textView != null && text != null) { // 為了避免substring刪除emoji等多個char的元素導致的錯誤擷取 int codePointCount = text.codePointCount(0, text.length()); for (int i = codePointCount; i >= 0; i--) { int offset = text.offsetByCodePoints(0, i); if (StringUtil.isEmpty((tmpTxt = text.substring(0, offset))) || (textView.getPaint().measureText(tmpTxt) + textView.getPaddingLeft() + textView.getPaddingRight()) < textView.getWidth()) { break; } } } return tmpTxt == null ? "" : tmpTxt; }