我的Android应用程序的问题是,当我计算其中包含emojis的字符串的长度时,每个表情符号计为两个或更多字符。我正在研究具有iOS版本的应用程序的Android版本。 iOS将每个表情符号统计为一个字符 - 当从iOS应用程序返回索引时,它假定每个表情符号都计为一个。
“你好我爱@team”
我想得到@team的索引,当我得到的唯一信息是iOS给出的索引是13,在android上这可能是14甚至15。
答案 0 :(得分:3)
这个答案建议使用java的Unicode支持代码点。
表情符号(grapheme)是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;
}
答案 1 :(得分:1)
以为我应该发布我的回答,因为我有两个赞成。
决定最好使用iOS索引作为&#34;真实&#34;和android的索引作为&#34; fake&#34;,这导致我必须将所有内容转换为iOS索引。 graphemeGetIndex获得iOS&#34;真实&#34;来自Java&#34; fake&#34;的索引那些,grahemeGetLength得到了真实的&#34;你需要的长度。
询问您是否有任何问题
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()});
}
}
答案 2 :(得分:1)
在尝试看到新的表情符号被释放后,我对此的回答是使用维护良好的库:
我导入了该库:
implementation 'com.vdurmont:emoji-java:4.0.0'
然后,我创建了一个实用程序方法来获取将表情符号计数为1的字符串的长度:
fun getLengthWithEmoji(s: String): Int{
var emojiCount = EmojiParser.extractEmojis(s).size;
var noEmojiString = EmojiParser.removeAllEmojis(s);
var emojiAndStringCount = emojiCount + noEmojiString.length;
return emojiAndStringCount;
}
通常要'获取字符串中的表情符号计数',我会使用此行:
var emojiCount = EmojiParser.extractEmojis(s).size;
这说明了所有最新的表情符号(取决于您的图书馆的最新信息)。检查其他人在库中创建的一些fork,因为在某些情况下它们添加了缺少的表情符号模式。