SpannableString的常用用法

1、BackgroundColorSpan 背景色
2、ClickableSpan 文本可点击,有点击事件
3、ForegroundColorSpan 文本颜色(前景色)
4、MaskFilterSpan 修饰效果,如模糊(BlurMaskFilter)、浮雕(EmbossMaskFilter)
5、MetricAffectingSpan 父类,一般不用
6、RasterizerSpan 光栅效果
7、StrikethroughSpan 删除线(中划线)
8、SuggestionSpan 相当于占位符
9、UnderlineSpan 下划线
10、AbsoluteSizeSpan 绝对大小(文本字体)
11、DynamicDrawableSpan 设置图片,基于文本基线或底部对齐。
12、ImageSpan 图片
13、RelativeSizeSpan 相对大小(文本字体)
14、ReplacementSpan 父类,一般不用
15、ScaleXSpan 基于x轴缩放
16、StyleSpan 字体样式:粗体、斜体等
17、SubscriptSpan 下标(数学公式会用到)
18、SuperscriptSpan 上标(数学公式会用到)
19、TextAppearanceSpan 文本外貌(包括字体、大小、样式和颜色)
20、TypefaceSpan 文本字体
21、URLSpan 文本超链接


以上是SpannableString的可用类型,这里只对ClickableSpan 、ImageSpan 、URLSpan 这3种做讲解。其他类似。
注:下文中,ClickableSpan的第二种方法,当要改变的数据有多次重复的时候,会有bug,解决办法,请参阅

http://blog.csdn.net/u014620028/article/details/51096023

先来布局文件:

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

    <TextView
        android:id="@+id/tv_show"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="50dp"
        android:text="Hello World!"/>
</LinearLayout>

有的地方会用到Toast,这里附上单例Toast(不用等上一个消失,下一个才会出现,只用一个)

public class Utils {
    private static Toast toast;
    /**
     * 单例吐司
     */
    public static void showToast(Context context, String msg) {
        if (toast == null) {
            toast = Toast.makeText(context, msg, Toast.LENGTH_SHORT);
        }
        toast.setText(msg);
        toast.show();
    }
}

代码讲解:
先初始化

String content = "滚滚长江东逝水,浪花淘尽英雄。是非成败转头空,青山依旧在,几度夕阳红。白发渔樵(qiáo)江渚(zhǔ)上,惯看秋月春风。一壶浊酒喜相逢,古今多少事,都付笑谈中。";

 SpannableString spannableString = new SpannableString(content);

1、ClickableSpan 第一种用法:给单个局部文字加颜色和点击事件

spannableString.setSpan(new ClickableSpan() {

            @Override
            public void updateDrawState(TextPaint ds) {
                super.updateDrawState(ds);
                //设置指定区域的文字变蓝色
                ds.setColor(Color.BLUE);
                //设置指定区域的文字有下划线
                ds.setUnderlineText(true);
            }

            @Override
            public void onClick(View widget) {

                Utils.showToast(MainActivity.this, "点击了");

            }
        }, 0, 7, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        //加上这句话,才有点击效果
        tv_show.setMovementMethod(LinkMovementMethod.getInstance());
        //把spannableString设置到TextView上
        tv_show.setText(spannableString);

效果图:
这里写图片描述

2、ClickableSpan 的第二种用法:给多个局部文字加颜色

ArrayList<String> list = new ArrayList<String>();

        list.add("长江");
        list.add("青山");
        list.add("夕阳红");
        list.add("秋月春风");

        for (int i = 0; i < list.size(); i++) {

            final String temp = list.get(i);
            String temp_content = content;

            int start = 0;
            while (temp_content.contains(temp)) {
                spannableString.setSpan(new ClickableSpan() {

                                            @Override
                                            public void updateDrawState(TextPaint ds) {
                                                // TODO Auto-generated method stub
                                                super.updateDrawState(ds);
                                                // 设置指定区域的文字变红色
                                                ds.setColor(Color.BLUE);
                                                //设置指定区域的文字有下划线
                                                ds.setUnderlineText(false);
                                            }

                                            @Override
                                            public void onClick(View widget) {
                                                Utils.showToast(MainActivity.this, "点击了" + temp);
                                            }

                                        }, start + temp_content.indexOf(temp), start + temp_content.indexOf(temp) + temp.length(),
                        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

                tv_show.setText(spannableString);
                tv_show.setMovementMethod(LinkMovementMethod.getInstance());
                start = temp_content.indexOf(temp) + temp.length();
                temp_content = temp_content.substring(start);
            }
        }

效果图:
这里写图片描述

3、URLSpan ,超链接,点击指定区域,根据输入的链接跳转。设计网络,最好加上网络权限

 <uses-permission android:name="android.permission.INTERNET" />

(1)调用默认的

spannableString.setSpan(new URLSpan("https://hao.360.cn/"), 2, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        tv_show.setText(spannableString);
        tv_show.setMovementMethod(LinkMovementMethod.getInstance());

效果图:
这里写图片描述

(2)默认是有下划线,颜色是红色,假如不喜欢,自己模仿URLSpan写一个

/**
         * 自定义的URLSpan,设置字体是蓝色,没有下划线
         */
        spannableString.setSpan(new MyUrlSpan("https://hao.360.cn/"), 10, 15, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        tv_show.setText(spannableString);
        tv_show.setMovementMethod(LinkMovementMethod.getInstance());

效果图:
这里写图片描述
URLSpanMyUrlSpan源码在附录。区别在于updateDrawState()

4、ImageSpan (把指定区域的文字,换成图片)

 Drawable d = getResources().getDrawable(R.mipmap.ic_launcher);
        d.setBounds(0, 0, 100, 100);
        spannableString.setSpan(new ImageSpan(d), 3, 6, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        tv_show.setText(spannableString);
        tv_show.setMovementMethod(LinkMovementMethod.getInstance());

效果图:
这里写图片描述

5、还可组合使用,这里以URLSpan 和ImageSpan 为例

 spannableString.setSpan(new MyUrlSpan("https://hao.360.cn/"), 10, 15, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

Drawable d = getResources().getDrawable(R.mipmap.ic_launcher);
d.setBounds(0, 0, 100, 100);
spannableString.setSpan(new ImageSpan(d), 3, 6, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv_show.setText(spannableString);
tv_show.setMovementMethod(LinkMovementMethod.getInstance());

效果图:
这里写图片描述


附录:
URLSpan 源码

/*
 * Copyright (C) 2006 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.text.style;

import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Parcel;
import android.provider.Browser;
import android.text.ParcelableSpan;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;

public class URLSpan extends ClickableSpan implements ParcelableSpan {

    private final String mURL;

    public URLSpan(String url) {
        mURL = url;
    }

    public URLSpan(Parcel src) {
        mURL = src.readString();
    }

    public int getSpanTypeId() {
        return getSpanTypeIdInternal();
    }

    /** @hide */
    public int getSpanTypeIdInternal() {
        return TextUtils.URL_SPAN;
    }

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel dest, int flags) {
        writeToParcelInternal(dest, flags);
    }

    /** @hide */
    public void writeToParcelInternal(Parcel dest, int flags) {
        dest.writeString(mURL);
    }

    public String getURL() {
        return mURL;
    }

    @Override
    public void onClick(View widget) {
        Uri uri = Uri.parse(getURL());
        Context context = widget.getContext();
        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
        intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
        try {
            context.startActivity(intent);
        } catch (ActivityNotFoundException e) {
            Log.w("URLSpan", "Actvity was not found for intent, " + intent.toString());
        }
    }
}

MyUrlSpan源码

package com.chen.demo;

import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.Parcel;
import android.provider.Browser;
import android.text.ParcelableSpan;
import android.text.TextPaint;
import android.text.style.ClickableSpan;
import android.util.Log;
import android.view.View;

/**
 * Created by lenovo on 2016/3/25.
 */
public class MyUrlSpan extends ClickableSpan implements ParcelableSpan {
    private final String mURL;

    public MyUrlSpan(String url) {
        mURL = url;
    }

    public MyUrlSpan(Parcel src) {
        mURL = src.readString();
    }

    public int getSpanTypeId() {
        return getSpanTypeIdInternal();
    }

    /**
     * @hide
     */
    public int getSpanTypeIdInternal() {
        return 0;
    }

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel dest, int flags) {
        writeToParcelInternal(dest, flags);
    }

    /**
     * @hide
     */
    public void writeToParcelInternal(Parcel dest, int flags) {
        dest.writeString(mURL);
    }

    public String getURL() {
        return mURL;
    }

    @Override
    public void onClick(View widget) {
        Uri uri = Uri.parse(getURL());
        Context context = widget.getContext();
        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
        intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
        try {
            context.startActivity(intent);
        } catch (ActivityNotFoundException e) {
            Log.w("URLSpan", "Actvity was not found for intent, " + intent.toString());
        }
    }

    @Override
    public void updateDrawState(TextPaint ds) {
        super.updateDrawState(ds);
        ds.setUnderlineText(false);
        ds.setColor(Color.BLUE);
    }
}

ClickableSpan源码

/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.text.style;

import android.text.TextPaint;
import android.view.View;

/**
 * If an object of this type is attached to the text of a TextView
 * with a movement method of LinkMovementMethod, the affected spans of
 * text can be selected.  If clicked, the {@link #onClick} method will
 * be called.
 */
public abstract class ClickableSpan extends CharacterStyle implements UpdateAppearance {

    /**
     * Performs the click action associated with this span.
     */
    public abstract void onClick(View widget);

    /**
     * Makes the text underlined and in the link color.
     */
    @Override
    public void updateDrawState(TextPaint ds) {
        ds.setColor(ds.linkColor);
        ds.setUnderlineText(true);
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值