Android關(guān)鍵詞標(biāo)紅(支持多個(gè)顏色和關(guān)鍵詞)

作為一個(gè)拿來主義者,最開始當(dāng)然要在網(wǎng)上尋找一番,找個(gè)Util省的自己寫了。
很快,就找到了一個(gè)......

public class PartColorTextView extends TextView {
    private final String SRM = "<font color=\"⊙\">%1$s</font>";//文字轉(zhuǎn)換Hmtl的格式固定不要?jiǎng)?    private final String OF = "⊙";//替換顏色的字符


    public PartColorTextView(Context context) {
        super(context);
    }

    public PartColorTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public PartColorTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    /**
     * @author WangHan
     * 創(chuàng)建時(shí)間:2016/11/2 14:38
     * 方法名:setPartText
     * 描述: 給文字顏色設(shè)置
     * 參數(shù):allText:全部文字 keyText:變色關(guān)鍵字 otherTextColor:默認(rèn)文字顏色 keyTextColor:要變顏色的字的顏色必須是個(gè)Color(getRe.getColor.)這樣獲得
     * 返回值:
     * 特殊注釋:該方法適合只有一個(gè)關(guān)鍵詞的時(shí)候
     */
    public void setPartText(String allText, String keyText, int otherTextColor, int keyTextColor) {
        String NF = String.format("#%06X", 0xFFFFFF & keyTextColor);
        String replace = SRM.replace(OF, NF);
        String format = String.format(replace, keyText);
        try {
            String textStr = allText.replaceAll(keyText, format);
            Spanned spanned = Html.fromHtml(textStr);
            setTextColor(otherTextColor);
            setText(spanned);
        } catch (PatternSyntaxException e) {
            e.printStackTrace();
        }
    }

    /**
     * @author WangHan
     * 創(chuàng)建時(shí)間:2016/11/2 14:38
     * 方法名:setPartText
     * 描述: 給文字顏色設(shè)置
     * 參數(shù):allText:全部文字 keyColorMap:用于一段話有多個(gè),且顏色要求不同的集合,Key是關(guān)鍵字,Value是Color  keyTextColor:要變顏色的字的顏色必須是個(gè)Color(getRe.getColor.)這樣獲得
     * 返回值:
     * 特殊注釋:該方法適合一段話有多個(gè)關(guān)鍵詞的時(shí)候
     */
    public void setPartText(String allText, HashMap<String, Integer> keyColorMap, int otherTextColor) {
        Spanned spanned = null;
        String textStr = null;
        Set<String> keySet = null;
        keySet = keyColorMap.keySet();
        for (String s : keySet) {
            String NF = String.format("#%06X", 0xFFFFFF & keyColorMap.get(s));
            String replace = SRM.replace(OF, NF);
            String format = String.format(replace, s);
            try {
                if (textStr == null) {
                    textStr = allText.replaceAll(s, format);
                } else {
                    textStr = textStr.replaceAll(s, format);
                }
            } catch (PatternSyntaxException e) {
                e.printStackTrace();
            }
        }

        setTextColor(otherTextColor);
        spanned = Html.fromHtml(textStr);
        setText(spanned);

    }
}

通過加html標(biāo)簽來改變樣式,不過在對(duì)比數(shù)據(jù)的時(shí)候發(fā)現(xiàn)了BUG。比如,文章中有“小學(xué)生”三個(gè)字,關(guān)鍵詞是“小學(xué)”、“學(xué)生”(實(shí)際中是類似的其他詞),而我只標(biāo)紅了“學(xué)生”。
想了想知道了原因,我在遍歷查找“小學(xué)”的時(shí)候如果找到了就給“小學(xué)”包了一個(gè)<font color=""></font>標(biāo)簽,那接下來遍歷查找“學(xué)生”的時(shí)候由于中間有標(biāo)簽隔著自然是不會(huì)被標(biāo)紅。
不對(duì)啊,那應(yīng)該標(biāo)紅的是“小學(xué)”結(jié)果怎么是“學(xué)生”呢??
原來這里使用的是HashMap, keyColorMap.keySet()得到的key的集合是無序的,也就是我第一個(gè)查找的是“學(xué)生”關(guān)鍵字,換成LinkedfHashMap就可以了,LinkedfHashMap是HashMap的子類,得到的是有序的。

那怎么解決將“小學(xué)生”都標(biāo)紅呢?
利用textview的復(fù)合文本。

  public static SpannableString matcherSearchTitle(String text,
                                                     LinkedHashMap<String,Integer> map) {
        Set<String> keySet = map.keySet();
        SpannableString s = new SpannableString(text);
        for (String key : keySet) {
            Pattern p = Pattern.compile(key);
            Matcher m = p.matcher(s);
            while (m.find()) {
                int start = m.start();
                int end = m.end();
                s.setSpan(new ForegroundColorSpan(map.get(key)), start, end,
                        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
        }
        return s;
    }

返回值直接利用textView.setText()就可以了簡(jiǎn)單好用,后來又發(fā)現(xiàn)一個(gè)問題......
如果文章中有“哈哈哈哈哈”,關(guān)鍵詞是“哈哈哈”,是不是需要將“哈哈哈哈哈”全部標(biāo)紅,結(jié)果卻是只標(biāo)紅了前三個(gè)“哈”。
不用想,那一定是API查找的方式是找到“哈哈哈”標(biāo)紅之后從第四個(gè)“哈”查找的,所以最后兩個(gè)“哈”必然不滿足“哈哈哈”關(guān)鍵詞的要求。
因此,想要全部標(biāo)紅那我就挨個(gè)字去遍歷即可。

 public static SpannableString matcherSearchTitle(String text,
                                                     LinkedHashMap<String,Integer> map) {
        Set<String> keySet = map.keySet();
        SpannableString s = new SpannableString(text);
        for (String key : keySet) {

            int a = text.indexOf(key);//*第一個(gè)出現(xiàn)的索引位置
            while (a != -1) {
                s.setSpan(new ForegroundColorSpan(map.get(key)), a, a+key.length(),
                        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                a = text.indexOf(key, a + 1);//*從這個(gè)索引往后開始第一個(gè)出現(xiàn)的位置
            }
        }
        return s;
    }

這個(gè)遍歷方式就可以一個(gè)字一個(gè)字的去遍歷。
最后,我們也不擔(dān)心順序問題了,可以將LinkedHashMap改回HashMap,畢竟HashMap效率高一些。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,291評(píng)論 25 708
  • ¥開啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個(gè)線程,因...
    小菜c閱讀 7,378評(píng)論 0 17
  • 感覺……這兒大概以后就是我的秋名山了_(:з」∠)_
    十七號(hào)橋柳樹閱讀 180評(píng)論 0 0
  • 今天給大家分享下怎么用微信公眾號(hào)賺錢的 首先必須注冊(cè)開通微信公眾號(hào),說到這里 不知道你們有多少人有注冊(cè)微信公眾號(hào)的...
    淡淡的紫夜閱讀 398評(píng)論 1 0
  • 文/吳 衍 ——追逐柜員之遐想 一 行走在六月的風(fēng)里,行走在拂曉的塍邊,我同稻田只隔了一條淺淺的梗線。 舉目遠(yuǎn)眺,...
    吳小衍閱讀 422評(píng)論 0 1

友情鏈接更多精彩內(nèi)容