Android富文本的学习一

1TextView的富文本介绍:

什么是富文本,大家都知道TextView可以显示文字,设置文字样式,利用富文本可以给TextView添加更多的样式,更加的类似h5网页,例如在一个TextView通常显示的文本样式是统一的,如果想对显示的同一段文本不同部分的文字设置不同的样式,颜色,大小等就需要用到富文本,富文本还可以利用TextView显示图片,设置点击事件等。

TextView想要实现富文本可以利用SpannableString(SpannableStringBuilder )和Html工具类,其实Html的工具类方式内部也是利用了SpannableString实现。
TextView可以利用setText设置文本,SpannableString实现了CharSequence,所以可以直接设置给TextView实现富文本。

常用span:

BackgroundColorSpan(背景色)、ForegroundColorSpan(设置字体颜色)、AbsoluteSizeSpan(设置字体大小)、UnderlineSpan(下划线),URLSpan(设置链接)、ClickableSpan(点击事件)、StyleSpan(样式,可以设置粗体,斜体等)、ImageSpan(图片Span)、RelativeSizeSpan(相对字体大小,就是设置字体大小的倍数)、ScaleXSpan(横向压缩字体)、SubscriptSpan(设置下标)、SuperscriptSpan(设置上标)、TextAppearanceSpan(也是设置文字样式)、TypefaceSpan(设置字体)、RasterizerSpan(设置光栅字样)、StrikethroughSpan(删除线)。
** 注意:
TextView必须设置 setMovementMethod(LinkMovementMethod.getInstance());
在使用ClickableSpan和继承ClickableSpan的时候,单击链接时凡是有要运行的动作,都必须设置MovementMethod对象。**

2 使用Span的方式

  • 利用SpannableString(SpannableStringBuilder )包装文本
  • 利用setSpan设置特定的span样式
    setSpan方法说明
    void setSpan (Object what, int start, int end, int flags)
    参数说明:
    what:生成的Span对象(特定span)
    start:开始位置,从0开始计数
    end:结束位置,应用span样式的文本长度为end-start
    flags:对于新插入字符的处理

Flags 取值:

Spanned.SPAN_EXCLUSIVE_EXCLUSIVE:前后都不包括,意义是如果在设置了span的文本前后插入新的SpannableString文本都不会应用span样式。
Spanned.SPAN_EXCLUSIVE_INCLUSIVE:前面不包括,后面包括,在设置的span前插入新的SpannableString不会应用span样式,在设置的span后插入则会应用相应span
Spanned.SPAN_INCLUSIVE_EXCLUSIVE:前面包括,后面不包括,在设置的span前插入新的SpannableString会应用span样式,在设置的span后插入则不会应用相应span
Spanned.SPAN_INCLUSIVE_INCLUSIVE:前后都包括,在设置的span前后插入新的SpannableString文本都会应用相应span

举例:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".SpanTestActivity">

    <TextView
        android:id="@+id/textview1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="17sp"
        android:layout_marginTop="10dp"
        android:text="用户名 回复 测试span:" />

    <TextView
        android:id="@+id/textview2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="17sp"
        android:layout_marginTop="10dp"
        android:text="用户名 回复 测试span:" />

    <TextView
        android:id="@+id/textview3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="17sp"
        android:layout_marginTop="10dp"
        android:text="用户名 回复 测试span:" />

    <TextView
        android:id="@+id/textview4"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="17sp"
        android:layout_marginTop="10dp"
        android:text="用户名 回复 测试span:" />

    <TextView
        android:id="@+id/textview5"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="17sp"
        android:layout_marginTop="10dp"
        android:text="用户名 回复 测试span:" />

    <TextView
        android:id="@+id/textview6"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="17sp"
        android:layout_marginTop="10dp"
        android:text="用户名 回复 测试span:" />

    <TextView
        android:id="@+id/textview7"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="17sp"
        android:layout_marginTop="10dp"
        android:text="用户名 回复 测试span:" />

</LinearLayout>
public class SpanTestActivity extends AppCompatActivity {

    private TextView mTextView1;
    private TextView mTextView2;
    private TextView mTextView3;
    private TextView mTextView4;
    private TextView mTextView5;
    private TextView mTextView6;
    private TextView mTextView7;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_span_test);
        mTextView1 = findViewById(R.id.textview1);
        mTextView2 = findViewById(R.id.textview2);
        mTextView3 = findViewById(R.id.textview3);
        mTextView4 = findViewById(R.id.textview4);
        mTextView5 = findViewById(R.id.textview5);
        mTextView6 = findViewById(R.id.textview6);
        mTextView7 = findViewById(R.id.textview7);
        SpannableStringBuilder spannableStringBuilder1 = new SpannableStringBuilder("测试富文本样式设");
        ForegroundColorSpan fspan1 = new ForegroundColorSpan(Color.RED);
        //从4-8,应用span的文本长度为8-4=4,所以就是从0开始第四个字符“本”开始,然后长度为4到"设“结束
        //应用了SPAN_INCLUSIVE_INCLUSIVE模式,所以后面添加的文本都会应用fspan的样式
        spannableStringBuilder1.setSpan(fspan1,4,8, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
        SpannableString textSpanned1 = new SpannableString("置字体颜色设置");
        spannableStringBuilder1.append(textSpanned1);
        mTextView1.setText(spannableStringBuilder1);

        SpannableStringBuilder spannableStringBuilder2 = new SpannableStringBuilder("测试富文本样式设");
        ForegroundColorSpan fspan2 = new ForegroundColorSpan(Color.RED);
        //从4-8,应用span的文本长度为8-4=4,所以就是从0开始第四个字符“本”开始,然后长度为4到"设“结束
        //应用了SPAN_INCLUSIVE_EXCLUSIVE模式,所以后面添加的文本不会应用fspan的样式
        spannableStringBuilder2.setSpan(fspan2,4,8, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        SpannableString textSpanned2 = new SpannableString("置字体颜色设置");
        spannableStringBuilder2.append(textSpanned2);
        mTextView2.setText(spannableStringBuilder2);


        SpannableStringBuilder spannableStringBuilder3 = new SpannableStringBuilder("测试富文本样式设");
        ForegroundColorSpan fspan3 = new ForegroundColorSpan(Color.RED);
        spannableStringBuilder3.setSpan(fspan3,4,8, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
        SpannableString textSpanned3 = new SpannableString("置字体颜色设置");
        spannableStringBuilder3.append(textSpanned3);
        spannableStringBuilder3.append("添加设置");
        mTextView3.setText(spannableStringBuilder3);

        SpannableStringBuilder spannableStringBuilder4 = new SpannableStringBuilder("测试富文本样式设");
        ForegroundColorSpan fspan4 = new ForegroundColorSpan(Color.RED);
        spannableStringBuilder4.setSpan(fspan4,4,8, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
        SpannableString textSpanned4 = new SpannableString("置字体颜色设置");
        textSpanned4.setSpan(new ForegroundColorSpan(Color.BLUE),0,7,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        spannableStringBuilder4.append(textSpanned4);
        spannableStringBuilder4.append("添加设置");
        mTextView4.setText(spannableStringBuilder4);

        SpannableStringBuilder spannableStringBuilder5 = new SpannableStringBuilder("测试富文本样式设");
        ForegroundColorSpan fspan5 = new ForegroundColorSpan(Color.RED);
        spannableStringBuilder5.setSpan(fspan5,4,8, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
        SpannableString textSpanned5 = new SpannableString("置字体颜色设置");
        textSpanned5.setSpan(new ForegroundColorSpan(Color.BLUE),0,7,Spanned.SPAN_INCLUSIVE_INCLUSIVE);
        spannableStringBuilder5.append(textSpanned5);
        spannableStringBuilder5.append("添加设置");
        mTextView5.setText(spannableStringBuilder5);


        SpannableString spannableString16 = new SpannableString("测试富文本样式设");
        ForegroundColorSpan fspan6 = new ForegroundColorSpan(Color.RED);
        spannableString16.setSpan(fspan6,4,8, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
        SpannableString spannableString26 = new SpannableString("置字体颜色设置");
        spannableString26.setSpan(new ForegroundColorSpan(Color.BLUE),0,5,Spanned.SPAN_INCLUSIVE_INCLUSIVE);

        mTextView6.setText(new SpannableStringBuilder().append(spannableString16).append(spannableString26).append("添加设置"));

    }
}

image

所以可以得出如下结论:

  • flags会影响添加的SpannableString文本的样式,四种flag分别表示是否影响前后添加的文本。
  • 受影响的文本长度为从start开始,长度为end-start,
  • 如果设置了影响添加的文本,但是新设置的文本内部应用了新的span样式,会首先应用内部文本添加的span,后续再添加文本也会受上次新添加Span的影响,如果新添加的文本不受上次添加span的影响,则会受更上层span的影响。

4 常用的Span举例:

上面已经展示了ForegroundColorSpan(设置字体颜色),下面介绍一些常用的span;

SpannableString span1 = new SpannableString("测试富文本样式设置");
SpannableString span2 = new SpannableString("测试富文本样式设置");
SpannableString span3 = new SpannableString("测试富文本样式设置");
SpannableString span4 = new SpannableString("测试富文本样式设置");
SpannableString span5 = new SpannableString("测试富文本样式设置");
SpannableString span6 = new SpannableString("测试富文本样式设置");
SpannableString span7 = new SpannableString("测试富文本样式设置");
BackgroundColorSpan bgSpan = new BackgroundColorSpan(Color.BLUE);
AbsoluteSizeSpan sizeSpan = new AbsoluteSizeSpan(22);
UnderlineSpan underline = new UnderlineSpan();
StrikethroughSpan deleteLine = new StrikethroughSpan();
SubscriptSpan subspan = new SubscriptSpan();

span1.setSpan(bgSpan,0,5,Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
mTextView1.setText(span1);

span2.setSpan(sizeSpan,0,4,Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
mTextView2.setText(span2);

span3.setSpan(underline,0,4,Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
mTextView3.setText(span3);

span4.setSpan(deleteLine,0,4,Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
mTextView4.setText(span4);

span5.setSpan(subspan,0,4,Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
mTextView5.setText(span5);

//必须设置LinkMovementMethod
mTextView6.setMovementMethod(LinkMovementMethod.getInstance());
ClickableSpan clickableSpan = new ClickableSpan() {
    @Override
    public void onClick(View widget) {
        Toast.makeText(SpanTestActivity.this,"click",Toast.LENGTH_SHORT).show();
    }
};
span6.setSpan(clickableSpan,0,5,Spanned.SPAN_INCLUSIVE_INCLUSIVE);
mTextView6.setText(span6);


//设置LinkMovementMethod ,利用默认浏览器打开
mTextView7.setMovementMethod(LinkMovementMethod.getInstance());
URLSpan urlSpan = new URLSpan("http://www.baidu.com");
span7.setSpan(urlSpan,0,9,Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
mTextView7.setText(span7);
image

5 Html工具类方式设置富文本

书写类似html格式代码,然后利用Html工具类也可以实现富文本,内部利用SpannableString。
支持的样式:


image
   String htmlText1 = "<big>大号字体</big>";
    mTextView1.setText(Html.fromHtml(htmlText1));

    String htmlText2 = "<i>大号字体<i>";
    mTextView2.setText(Html.fromHtml(htmlText2));

    String htmlText3 = "大号<br>字体";
    mTextView3.setText(Html.fromHtml(htmlText3));

    String htmlText4 = "大号<p>字体";
    mTextView4.setText(Html.fromHtml(htmlText4));

    String htmlText5 = "<img src=\"ic_launcher\"/>";
    mTextView5.setText(Html.fromHtml(htmlText5, new Html.ImageGetter() {
        @Override
        public Drawable getDrawable(String source) {
            Drawable draw = null;
            try {
                Field field = R.mipmap.class.getField(source);
                int resourceId = Integer.parseInt(field.get(null).toString());
                draw = getResources().getDrawable(resourceId);
                draw.setBounds(0, 0, draw.getIntrinsicWidth(), draw.getIntrinsicHeight());
            } catch (Exception e) {
                e.printStackTrace();
            }
            return draw;
        }
    }, null));

}
image
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,271评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,725评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,252评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,634评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,549评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,985评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,471评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,128评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,257评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,233评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,235评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,940评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,528评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,623评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,858评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,245评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,790评论 2 339

推荐阅读更多精彩内容