最近杭研院的stone app有接入搜索引擎的頁面。當用戶輸入關(guān)鍵字時,搜索引擎返回匹配的結(jié)果。匹配的結(jié)果里的對應關(guān)鍵字做高亮顯示。如下圖所示

服務(wù)器點返回的結(jié)果為帶標簽的字符串。比如,搜索"故人"關(guān)鍵字,返回的字符串如下
等閑變卻<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,如果含有l(wèi)eft,則掃描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。直到掃描結(jié)束。
6、根據(jù)下表表以及newText,構(gòu)造SpannableString,返回。