我的android應用程序的問題是,當我計算其中包含emojis的字符串的長度時,每個表情符號會計爲兩個或多個字符。我正在研究具有iOS版本的應用的Android版本。 iOS將每個表情符號統計爲一個字符 - 當索引從iOS應用程序返回時,它假定每個表情符號都被計爲一個。通過僅將emojis作爲一個字符來計算字符串中的字符正確索引
「嗨,我愛@team」
我想獲得@team,指數當我的唯一信息是通過iOS版給出的指數是13,在Android這也許14甚至15
我的android應用程序的問題是,當我計算其中包含emojis的字符串的長度時,每個表情符號會計爲兩個或多個字符。我正在研究具有iOS版本的應用的Android版本。 iOS將每個表情符號統計爲一個字符 - 當索引從iOS應用程序返回時,它假定每個表情符號都被計爲一個。通過僅將emojis作爲一個字符來計算字符串中的字符正確索引
「嗨,我愛@team」
我想獲得@team,指數當我的唯一信息是通過iOS版給出的指數是13,在Android這也許14甚至15
以爲我應該發佈我的答案,因爲我有兩個upvotes。
決定最好將iOS索引作爲「真實」,Android索引作爲「假」,這導致我不得不將所有內容都轉換爲iOS索引。 graphemeGetIndex從Java的「假」中獲得iOS的「真實」索引,而grahemeGetLength則獲得「真正」的長度以滿足您的需求。
問你是否有任何問題
public static int graphemeLength(String s) {
BreakIterator it = BreakIterator.getCharacterInstance();
it.setText(s);
int count = 0;
while (it.next() != BreakIterator.DONE) {
count++;
}
return count;
}
public static int graphemeGetIndex(String wholeString, int mIndex) {
BreakIterator it = BreakIterator.getCharacterInstance();
int realStartIndex = 0;
if (mIndex >= 0) {
String partString = wholeString.substring(0, mIndex);
it.setText(partString);
while (it.next() != BreakIterator.DONE) {
realStartIndex++;
}
}
return realStartIndex;
}
private void recalculateIndices() {
for (final UserMention mention : mMentions) {
final int startFake = mCurrentText.indexOf("@" + mention.getName());
final int startReal = graphemeGetIndex(mCurrentText, startFake);
mention.setRealIndices(new int[]{startReal, startReal + graphemeLength(mention.getName())});
mention.setJavaFakeIndices(new int[]{startFake, startFake + mention.getName().length()});
}
}
這個答案建議使用碼點 Java的Unicode支持。
表情符號符號(字形)是Unicode 代碼點。 Java在內部也使用Unicode,但通常是(UTF-16)
char
一個兩字節的代碼,而且一個表情符號的代碼點的Unicode號碼要高得多。因此,java使用幾個字符。以emojis開頭。
但是可以在java中使用代碼點。 Java 8有一些額外的幫助;不需要,但我希望Android已經達到某種功能。
以在代碼點長度:
int codePointsLength(String s) {
int n = 0;
for (int i = 0; i < s.length();) {
int codePoint = s.codePointAt(i);
i += Character.charCount(codePoint);
++n;
}
return n;
}
int codePointsLength(String s) {
return (int) s.codePoints().count(); // Java 8.
}
使從一個表情符號的字符串,利用Unicode代碼點:
final int RAISED_EYEBROW = 0x1f928; // U+1F928.
String s = new String(new int[] {RAISED_EYEBROW}, 0, 1);
查找由代碼點索引的字符串的位置:
int codePointIndexOf(String s, int codePoint) {
int n = 0;
for (int i = 0; i < s.length();) {
int cp = s.codePointAt(i);
if (cp == codePoint) {
return n;
}
i += Character.charCount(cp);
++n;
}
return -1;
}
// Java 9 takeWhile.
int codePointIndexOf(String s, int codePoint) {
int totalCount = (int) s.codePoints().count();
int count = (int) s.codePoints().takeWhile(cp -> cp != codePoint).count();
return count >= totalCount ? -1 : count;
}