Android 中 TextView 部分文字有不同的顏色和部分文字點(diǎn)擊事件

一脑蠕、前言:

我們?cè)陂_發(fā)中,經(jīng)常遇到一段文本跪削,需要單獨(dú)給它部分文字設(shè)置不同的樣式谴仙,有的文字設(shè)置為粗體,有的文字設(shè)置特殊的顏色碾盐,有的地方要加入表情晃跺,遇到數(shù)學(xué)公式還可能要設(shè)置上下標(biāo),這時(shí)候該怎么辦呢毫玖?

有的人會(huì)采用不同的 TextView掀虎,這樣就可以完美解決了凌盯。先不說這個(gè)方法行不行得通,事實(shí)上烹玉,若采用這種方式驰怎,當(dāng)碰上一段文字需要設(shè)置非常多的樣式時(shí),光是這一堆TextView就夠浪費(fèi)資源的了二打,布局還復(fù)雜县忌,也不利于維護(hù),因此這種方式一般不會(huì)被采用继效。

那么有其他辦法嗎症杏?有,并且還很簡(jiǎn)單瑞信,今天介紹的這個(gè)SpannableString就是用來解決這個(gè)問題的鸳慈。

xml 代碼片段:

     <TextView
        android:id="@+id/tv_value"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="要變色的值"
        />

第一種方法:

        //方法一:
        TextView tvValue = findViewById(R.id.tv_value);
        String str="默認(rèn)顏色<font color='#FF0000'><small>紅顏色 
       </small></font>";
        tvValue.setTextSize(18);
        tvValue.setText(Html.fromHtml(str));

第二種方法:
采用 SpannableString實(shí)現(xiàn)

二、 SpannableString使用:

1喧伞、SpannableString走芋、SpannableStringBuilder與String的關(guān)系

首先SpannableString、SpannableStringBuilder基本上與String差不多潘鲫,也是用來存儲(chǔ)字符串翁逞,但它們倆的特殊就在于有一個(gè)SetSpan()函數(shù),能給這些存儲(chǔ)的String添加各種格式或者稱樣式(Span)溉仑,將原來的String以不同的樣式顯示出來挖函,比如在原來String上加下劃線、加背景色浊竟、改變字體顏色怨喘、用圖片把指定的文字給替換掉,等等振定。所以必怜,總而言之,SpannableString后频、SpannableStringBuilder與String一樣梳庆, 首先也是傳字符串,但SpannableString卑惜、SpannableStringBuilder可以對(duì)這些字符串添加額外的樣式信息膏执,但String則不行。

注意:如果這些額外信息能被所用的方式支持露久,比如將SpannableString傳給TextView更米;也有對(duì)這些額外信息不支持的,比如前一章講到的Canvas繪制文字毫痕,對(duì)于不支持的情況征峦,SpannableString和SpannableStringBuilder就是退化為String類型纸巷,直接顯示原來的String字符串,而不會(huì)再顯示這些附加的額外信息眶痰。

2瘤旨、SpannableString與SpannableStringBuilder區(qū)別

它們的區(qū)別在于 SpannableString像一個(gè)String一樣,構(gòu)造對(duì)象的時(shí)候傳入一個(gè)String竖伯,之后再無法更改String的內(nèi)容存哲,也無法拼接多個(gè) SpannableString;而SpannableStringBuilder則更像是StringBuilder七婴,它可以通過其append()方法來拼接多個(gè)String祟偷;

image

3、創(chuàng)建方式

SpannableStringBuilder spannableString = new SpannableStringBuilder("如果我是陳奕迅");

設(shè)置

spannableString.setSpan(Object what, int start, int end, int flags);

這里講解一下幾個(gè)參數(shù)的意義:

  • what:對(duì)SpannableString進(jìn)行潤(rùn)色的各種Span打厘;
  • int:需要潤(rùn)色文字段開始的下標(biāo)修肠;
  • end:需要潤(rùn)色文字段結(jié)束的下標(biāo);
  • flags:決定開始和結(jié)束下標(biāo)是否包含的標(biāo)志位户盯,有四個(gè)參數(shù)可選
  1. SPAN_INCLUSIVE_EXCLUSIVE:包括開始下標(biāo)嵌施,但不包括結(jié)束下標(biāo)
  2. SPAN_EXCLUSIVE_INCLUSIVE:不包括開始下標(biāo),但包括結(jié)束下標(biāo)
  3. SPAN_INCLUSIVE_INCLUSIVE:既包括開始下標(biāo)莽鸭,又包括結(jié)束下標(biāo)
  4. SPAN_EXCLUSIVE_EXCLUSIVE:不包括開始下標(biāo)吗伤,也不包括結(jié)束下標(biāo)

這里涉及到一個(gè)重要的角色,就是各種各樣的span硫眨,它決定我們要對(duì)文字的進(jìn)行怎樣的潤(rùn)飾足淆,而后三個(gè)參數(shù)決定潤(rùn)飾哪些文字,為了方便起見礁阁,后面的flags默認(rèn)都使用SPAN_INCLUSIVE_EXCLUSIVE模式巧号。

3、 ForegroundColorSpan

代碼

SpannableStringBuilder spannableString = new SpannableStringBuilder("如果我是陳奕迅");
ForegroundColorSpan foregroundColorSpan1 = new ForegroundColorSpan(Color.GREEN);
ForegroundColorSpan foregroundColorSpan2 = new ForegroundColorSpan(Color.GREEN);
spannableString.setSpan(foregroundColorSpan1, 0, 2, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
spannableString.setSpan(foregroundColorSpan2, 4, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
mTextView.setText(spannableString);

  • ForegroundColorSpan:前景色姥闭,也就是對(duì)文字上色丹鸿,顏色設(shè)置為GREEN,start為4泣栈,end為7卜高,應(yīng)該是“陳奕迅”三個(gè)字顯示為綠色。
  • “如果” 也是綠色
    注意:必須new兩個(gè)ForegroundColorSpan南片,否則只有一個(gè)地方字體變綠

4庭敦、 BackgroudColorSpan

代碼

SpannableStringBuilder spannableString = new SpannableStringBuilder("如果我是陳奕迅");
BackgroundColorSpan backgroundColorSpan = new BackgroundColorSpan(Color.GREEN);
spannableString.setSpan(backgroundColorSpan, 4, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
mTextView.setText(spannableString);

BackgroudColorSpan:與ForegroundColorSpan類似疼进,對(duì)文字背景上色

5、 AbsoluteSizeSpan

代碼

SpannableStringBuilder spannableString = new SpannableStringBuilder("如果我是陳奕迅");
AbsoluteSizeSpan absoluteSizeSpan = new AbsoluteSizeSpan(40, true);
spannableString.setSpan(absoluteSizeSpan, 4, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
mTextView.setText(spannableString);

AbsoluteSizeSpan:設(shè)置字體的相絕對(duì)大小秧廉,40表示文字大小伞广,true表示單位為dip拣帽,若為false則表示px

6、 UnderlineSpan (下劃線)

代碼

SpannableStringBuilder spannableString = new SpannableStringBuilder("如果我是陳奕迅");
UnderlineSpan underlineSpan = new UnderlineSpan();
spannableString.setSpan(underlineSpan, 4, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
mTextView.setText(spannableString);

UnderlineSpan:設(shè)置文字下劃線嚼锄,強(qiáng)調(diào)突出文字時(shí)可以使用該span

7减拭、StrikethroughSpan (中間刪除線)

代碼

SpannableStringBuilder spannableString = new SpannableStringBuilder("如果我是陳奕迅");
StrikethroughSpan strikethroughSpan = new StrikethroughSpan();
spannableString.setSpan(strikethroughSpan, 4, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
mTextView.setText(spannableString);

8、 SuperscriptSpan (上標(biāo))

代碼

SpannableStringBuilder spannableString = new SpannableStringBuilder("如果我是陳奕迅");
SuperscriptSpan superscriptSpan = new SuperscriptSpan();
RelativeSizeSpan relativeSizeSpan = new RelativeSizeSpan(0.8f);
spannableString.setSpan(relativeSizeSpan, 4, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
spannableString.setSpan(superscriptSpan, 4, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
mTextView.setText(spannableString);

SuperscriptSpan:設(shè)置文字為上標(biāo)

9区丑、部分文字的點(diǎn)擊事件

效果圖:

image
        TextView tv1 = view.findViewById(R.id.tv1);
        String content = " 歡迎來到SumanSoul為了更好地向用戶提供服務(wù)拧粪,未經(jīng)用戶同意,SumanSoul不會(huì)自動(dòng)收集沧侥、獲取可霎、共享或?qū)ν馓峁┯脩魝€(gè)人信息;你可以隨時(shí)查看宴杀、更正或刪除你的個(gè)人信息癣朗,SumanSoul也提供用戶注銷功能。";
        tv_content.setText(content.replace(" ", ""));
        SpannableStringBuilder spannableString = new SpannableStringBuilder("點(diǎn)擊查看完整「用戶協(xié)議」和「隱私政策」");
        spannableString.setSpan(new TextAgreementClick(), 6, 12, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        spannableString.setSpan(new TextPrivacyClick(), 13, spannableString.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        //設(shè)置點(diǎn)擊事件旺罢,加上這句話才有效果
        tv1.setMovementMethod(LinkMovementMethod.getInstance());
         //設(shè)置點(diǎn)擊后的顏色為透明(有默認(rèn)背景)
       tv1.setHighlightColor(BaseApplication.getInstance().getResources().getColor(R.color.transparent));
        tv1.setText(spannableString);

  <!-- 透明背景色-->
    <color name="transparent" tools:ignore="MissingDefaultResource">#00000000</color>

下面是TextAgreementClick實(shí)現(xiàn)ClickableSpan

    private class TextAgreementClick extends ClickableSpan{

        @Override
        public void updateDrawState(TextPaint ds) {
            super.updateDrawState(ds);
            //設(shè)置文本的顏色
            ds.setColor(Color.RED);
            //超鏈接形式的下劃線旷余,false 表示不顯示下劃線,true表示顯示下劃線
            ds.setUnderlineText(false);
        }

        @Override
        public void onClick(View widget) {
           // 執(zhí)行點(diǎn)擊邏輯
        }
    }

三扁达、總結(jié)

  • ForegroundColorSpan:前景色
  • BackgroundColorSpan:背景色
  • ClickableSpan:抽象類荣暮,可點(diǎn)擊效果,重寫onClick方法響應(yīng)點(diǎn)擊事件
  • URLSpan:超鏈接
  • MaskFilterSpan:EmbossMaskFilter浮雕效果罩驻,BlurMaskFilter模糊效果
  • RelativeSpan:文字相對(duì)大小
  • AbsoluteSpan:文字絕對(duì)大小
  • ScaleXSpan:x軸縮放
  • styleSpan:文字樣式
  • TypefaceSpan:文字字體類型
  • TextApearanceSpan:文字外貌
  • UnderlineSpan:下劃線
  • StrikeThroughSpan:刪除線
  • SuperscriptSpan:上標(biāo)
  • SubscriptSpan:下標(biāo)
  • ImageSpan:圖片

這些Span能夠很好地幫助我們潤(rùn)色文字穗酥,以非常簡(jiǎn)單地方式獲得復(fù)雜和絢麗的文字效果,著實(shí)是開發(fā)中的一大利器惠遏,喜歡的朋友收藏備用吧砾跃。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市节吮,隨后出現(xiàn)的幾起案子抽高,更是在濱河造成了極大的恐慌,老刑警劉巖透绩,帶你破解...
    沈念sama閱讀 211,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件翘骂,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡帚豪,警方通過查閱死者的電腦和手機(jī)碳竟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來狸臣,“玉大人莹桅,你說我怎么就攤上這事≈蛞啵” “怎么了诈泼?”我有些...
    開封第一講書人閱讀 157,435評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵懂拾,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我铐达,道長(zhǎng)岖赋,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,509評(píng)論 1 284
  • 正文 為了忘掉前任瓮孙,我火速辦了婚禮唐断,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘衷畦。我一直安慰自己栗涂,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,611評(píng)論 6 386
  • 文/花漫 我一把揭開白布祈争。 她就那樣靜靜地躺著斤程,像睡著了一般。 火紅的嫁衣襯著肌膚如雪菩混。 梳的紋絲不亂的頭發(fā)上忿墅,一...
    開封第一講書人閱讀 49,837評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音沮峡,去河邊找鬼疚脐。 笑死,一個(gè)胖子當(dāng)著我的面吹牛邢疙,可吹牛的內(nèi)容都是我干的棍弄。 我是一名探鬼主播,決...
    沈念sama閱讀 38,987評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼疟游,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼呼畸!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起颁虐,我...
    開封第一講書人閱讀 37,730評(píng)論 0 267
  • 序言:老撾萬榮一對(duì)情侶失蹤蛮原,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后另绩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體儒陨,經(jīng)...
    沈念sama閱讀 44,194評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,525評(píng)論 2 327
  • 正文 我和宋清朗相戀三年笋籽,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蹦漠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,664評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡干签,死狀恐怖携龟,靈堂內(nèi)的尸體忽然破棺而出睦柴,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 34,334評(píng)論 4 330
  • 正文 年R本政府宣布吁脱,位于F島的核電站,受9級(jí)特大地震影響旧困,放射性物質(zhì)發(fā)生泄漏敷搪。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,944評(píng)論 3 313
  • 文/蒙蒙 一留量、第九天 我趴在偏房一處隱蔽的房頂上張望窄赋。 院中可真熱鬧,春花似錦楼熄、人聲如沸忆绰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,764評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽错敢。三九已至,卻和暖如春缕粹,著一層夾襖步出監(jiān)牢的瞬間稚茅,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,997評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工平斩, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留亚享,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,389評(píng)論 2 360
  • 正文 我出身青樓绘面,卻偏偏與公主長(zhǎng)得像欺税,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子揭璃,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,554評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容