最近杭研院的stone app有接入搜索引擎的页面。当用户输入关键字时,搜索引擎返回匹配的结果。匹配的结果里的对应关键字做高亮显示。如下图所示
服务器点返回的结果为带标签的字符串。比如,搜索"故人"关键字,返回的字符串如下
等闲变却<gaoliang>故人</gaoling>心,却道<gaoliang>故人</gaoliang>心易变。
客户端需要识别被高亮的字符串,并予以高亮显示。代码如下:
/**
* 将left和right标注的文本高亮出来,高亮
*@param text
*@param left
*@param right
*@return
*/
public SpannableString highlightStr(String text,String left,String right){
if(text ==null){
return null;
}
if(text.trim().length() ==0){
return null;
}
if(left ==null|| left.trim().length() ==0){
return null;
}
if(right ==null|| right.trim().length() ==0){
return null;
}
int leftLen = left.length();
int rightLen = right.length();
int totalLen = leftLen + rightLen;
if(text.trim().length() <= totalLen){
return new SpannableString(text);
}
StringBuffer textNew =new StringBuffer(text);
int pivot =0;
int length = text.length();
Map pairs =new HashMap();
Map newPairs =new HashMap();
int times =0;
while(pivot != length -1){
int leftIndex = text.indexOf(left,pivot);
if(leftIndex != -1){
int newLeftIndex = leftIndex - totalLen*times;
textNew.delete(newLeftIndex, newLeftIndex+leftLen);
int rightIndex = text.indexOf(right,leftIndex);
if(rightIndex != -1){
int newRightIndex = rightIndex - totalLen*(times+1)+rightLen;
textNew.delete(newRightIndex, newRightIndex+rightLen);
times++;
pairs.put(leftIndex,rightIndex );
newPairs.put(newLeftIndex, newRightIndex);
pivot = rightIndex;
}else{
pivot = leftIndex;
}
}
pivot++;
}
SpannableString sp =new SpannableString(textNew);
for(Map.Entry entry:newPairs.entrySet()) {
Integer start = entry.getKey();
Integer end = entry.getValue();
sp.setSpan(new ForegroundColorSpan(Color.RED), start, end, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
}
return sp;
}
算法要点:
1、拷贝text为newText。
2、在text中扫描left,如果含有left,则扫描right。记录下leftIndex,rightIndex。
3、记录newLeftIndex与newRightIndex。记录到newPairs中。
//totalLen=leftLen+rightLen
newLeftIndex = leftIndex - totalLen*i,
newRightIndex = rightIndex - totalLen*(i+1)+rightLen;
4、newText中删除(newLeftIndex, newLeftIndex+leftLen)的标签,删除(newRightIndex, newRightIndex+rightLen)的标签。
5、i++,返回2。直到扫描结束。
6、根据下表表以及newText,构造SpannableString,返回。