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

一、前言:

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

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

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

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差不多,也是用來(lái)存儲(chǔ)字符串,但它們倆的特殊就在于有一個(gè)SetSpan()函數(shù),能給這些存儲(chǔ)的String添加各種格式或者稱(chēng)樣式(Span),將原來(lái)的String以不同的樣式顯示出來(lái),比如在原來(lái)String上加下劃線(xiàn)、加背景色、改變字體顏色、用圖片把指定的文字給替換掉,等等。所以,總而言之,SpannableString、SpannableStringBuilder與String一樣, 首先也是傳字符串,但SpannableString、SpannableStringBuilder可以對(duì)這些字符串添加額外的樣式信息,但String則不行。

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

2、SpannableString與SpannableStringBuilder區(qū)別

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


圖片.png

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)色文字段開(kāi)始的下標(biāo);
  • end:需要潤(rùn)色文字段結(jié)束的下標(biāo);
  • flags:決定開(kāi)始和結(jié)束下標(biāo)是否包含的標(biāo)志位,有四個(gè)參數(shù)可選
  1. SPAN_INCLUSIVE_EXCLUSIVE:包括開(kāi)始下標(biāo),但不包括結(jié)束下標(biāo)
  2. SPAN_EXCLUSIVE_INCLUSIVE:不包括開(kāi)始下標(biāo),但包括結(jié)束下標(biāo)
  3. SPAN_INCLUSIVE_INCLUSIVE:既包括開(kāi)始下標(biāo),又包括結(jié)束下標(biāo)
  4. SPAN_EXCLUSIVE_EXCLUSIVE:不包括開(kāi)始下標(biāo),也不包括結(jié)束下標(biāo)

這里涉及到一個(gè)重要的角色,就是各種各樣的span,它決定我們要對(duì)文字的進(jìn)行怎樣的潤(rùn)飾,而后三個(gè)參數(shù)決定潤(rùn)飾哪些文字,為了方便起見(jià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類(lèi)似,對(duì)文字背景上色

5、 AbsoluteSizeSpan

1、代碼

SpannableStringBuilder spannableString = new SpannableStringBuilder("如果我是陳奕迅");
AbsoluteSizeSpan absoluteSizeSpan = new AbsoluteSizeSpan((int) BaseApplication.getContext().getResources().getDimension(R.dimen.sp_20), true);
spannableString.setSpan(absoluteSizeSpan, 4, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
mTextView.setText(spannableString);

AbsoluteSizeSpan:設(shè)置字體的絕對(duì)大小,40表示文字大小,true表示單位為dip,若為false則表示px。

2、代碼

 String content = "¥"+CommonUtils.getDouble2Money(walletBean.getTotal_income(),false);
                Log.d("LUO","====content: "+content);
                SpannableStringBuilder monthMoney1 = new SpannableStringBuilder(content);
                monthMoney1.setSpan(new RelativeSizeSpan(0.7f), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                monthMoney1.setSpan(new RelativeSizeSpan(1f), 1, monthMoney1.length()-3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                monthMoney1.setSpan(new RelativeSizeSpan(0.7f), monthMoney1.length()-3, monthMoney1.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                tvMonthMoney.setText(monthMoney1);

RelativeSizeSpan:設(shè)置文字的相對(duì)大小,相對(duì)于原先文字的0.7f的大小。

6、 UnderlineSpan (下劃線(xiàn))

代碼

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

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

7、StrikethroughSpan (中間刪除線(xiàn))

代碼

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)擊事件

效果圖:


圖片.png
        TextView tv1 = view.findViewById(R.id.tv1);
        String content = " 歡迎來(lái)到SumanSoul為了更好地向用戶(hù)提供服務(wù),未經(jīng)用戶(hù)同意,SumanSoul不會(huì)自動(dòng)收集、獲取、共享或?qū)ν馓峁┯脩?hù)個(gè)人信息;你可以隨時(shí)查看、更正或刪除你的個(gè)人信息,SumanSoul也提供用戶(hù)注銷(xiāo)功能。";
        tv_content.setText(content.replace(" ", ""));
        SpannableStringBuilder spannableString = new SpannableStringBuilder("點(diǎn)擊查看完整「用戶(hù)協(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)擊事件,加上這句話(huà)才有效果
        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);
            //超鏈接形式的下劃線(xiàn),false 表示不顯示下劃線(xiàn),true表示顯示下劃線(xiàn)
            ds.setUnderlineText(false);
        }

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

三、總結(jié)

  • ForegroundColorSpan:前景色
  • BackgroundColorSpan:背景色
  • ClickableSpan:抽象類(lèi),可點(diǎn)擊效果,重寫(xiě)onClick方法響應(yīng)點(diǎn)擊事件
  • URLSpan:超鏈接
  • MaskFilterSpan:EmbossMaskFilter浮雕效果,BlurMaskFilter模糊效果
  • RelativeSpan:文字相對(duì)大?。ú捎?.5f,是原先的字體大小的1/2)
  • AbsoluteSpan:文字絕對(duì)大?。ㄔO(shè)置字體的相絕對(duì)大小,40表示文字大小,true表示單位為dip,若為false則表示px)
  • ScaleXSpan:x軸縮放
  • styleSpan:文字樣式
  • TypefaceSpan:文字字體類(lèi)型
  • TextApearanceSpan:文字外貌
  • UnderlineSpan:下劃線(xiàn)
  • StrikeThroughSpan:刪除線(xiàn)
  • SuperscriptSpan:上標(biāo)
  • SubscriptSpan:下標(biāo)
  • ImageSpan:圖片

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

最后編輯于
?著作權(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)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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