Android中带变音符号的阿拉伯语单词高亮异常问题
解决阿拉伯语含变音符号文本的搜索高亮错位问题
问题核心:阿拉伯语文本中的变音符号(如َ、ّ、ُ)会占用额外字符位,导致移除变音后的归一化字符串与原字符串的索引无法一一对应。直接用归一化字符串的搜索索引去原字符串中高亮,会出现位置偏移。
解决方案思路
通过建立归一化字符串索引与原字符串索引的映射关系,将归一化后的搜索位置转换为原字符串中的正确位置,再执行高亮操作。
具体实现步骤
生成索引映射表
遍历原字符串,记录每个归一化后字符对应的原字符串起始索引。遇到变音符号时跳过,不增加归一化索引计数。转换搜索索引
用归一化字符串找到目标词的起始/结束索引后,通过映射表转换为原字符串中的真实起始/结束位置。
代码实现
首先实现生成索引映射的工具方法:
/** * 生成原字符串到归一化字符串的索引映射表 * @param original 带变音符号的原字符串 * @return 数组,下标为归一化字符串的索引,值为原字符串对应的起始位置 */ private int[] buildIndexMap(String original) { List<Integer> indexMap = new ArrayList<>(); for (int i = 0; i < original.length(); i++) { char c = original.charAt(i); // 判断是否为阿拉伯语变音符号(Unicode范围:0x064B-0x0652) if (!(c >= 0x064B && c <= 0x0652)) { indexMap.add(i); } } // 转换为数组 int[] mapArray = new int[indexMap.size()]; for (int i = 0; i < indexMap.size(); i++) { mapArray[i] = indexMap.get(i); } return mapArray; }
然后修改原高亮代码:
// 1. 归一化处理 String normalizedSearchText = removeDiacritics(searchText.toLowerCase().trim()); String normalizedContent = removeDiacritics(content.toLowerCase().trim()); int startNormalized = normalizedContent.indexOf(normalizedSearchText); if (startNormalized != -1) { // 2. 生成原字符串与归一化字符串的索引映射 int[] indexMap = buildIndexMap(content); int endNormalized = startNormalized + normalizedSearchText.length(); // 3. 转换为原字符串的真实索引 int startOriginal = indexMap[startNormalized]; int endOriginal; if (endNormalized < indexMap.length) { endOriginal = indexMap[endNormalized]; } else { // 处理目标词在文本末尾的情况 endOriginal = content.length(); } // 4. 执行高亮 Spannable spannable = new SpannableString(content); BackgroundColorSpan backgroundColorSpan = new BackgroundColorSpan(Color.YELLOW); spannable.setSpan(backgroundColorSpan, startOriginal, endOriginal, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); binding.tvContent.setText(spannable); }
补充说明
- 变音符号的Unicode范围是
U+064B到U+0652,判断逻辑可覆盖绝大多数阿拉伯语变音场景。 - 若
removeDiacritics函数处理逻辑特殊,需同步调整buildIndexMap中的字符判断条件,确保两者对“需移除的变音符号”定义一致。
内容的提问来源于stack exchange,提问作者MRS
相关产品推荐
相关产品推荐

