使用SpannableString设置部分文字大小、颜色、超链接、点击事件

Android中需要给TextView中的个别字设置为超链接,或者设置个别字的颜色、字体等,需要用到Spannable对象。

效果如下:
使用SpannableString设置部分文字大小、颜色、超链接、点击事件_第1张图片
baidu和youku字段做了autolink,设置字体大小和颜色,youku并取消了下划线。

private void initView() {
        TextView textView = (TextView) findViewById(R.id.tv_content);
        String content = textView.getText().toString();
        // This is a test,you can click baidu or youku.
        SpannableString ss = new SpannableString(content);
        // flag:标识在 Span 范围内的文本前后输入新的字符时是否把它们也应用这个效果
        //  Spanned.SPAN_EXCLUSIVE_EXCLUSIVE(前后都不包括)、
        //  Spanned.SPAN_INCLUSIVE_EXCLUSIVE(前面包括,后面不包括)、
        // Spanned.SPAN_EXCLUSIVE_INCLUSIVE(前面不包括,后面包括)、
        // Spanned.SPAN_INCLUSIVE_INCLUSIVE(前后都包括)
        // 设置网络超链接
        ss.setSpan(new URLSpan("http://www.baidu.com"), content.indexOf("baidu"), content.indexOf(" or"), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        ss.setSpan(new URLSpan("http://www.youku.com"), content.indexOf("youku"), ss.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        // 设置字体颜色
        ss.setSpan(new ForegroundColorSpan(Color.parseColor("#ff0000")), content.indexOf("baidu"), content.indexOf(" or"), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        ss.setSpan(new ForegroundColorSpan(Color.parseColor("#ff00ff")), content.indexOf("youku"), ss.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        // 设置字体大小
        ss.setSpan(new AbsoluteSizeSpan(sp2px(this, 25)), content.indexOf("baidu"), content.indexOf(" or"), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        ss.setSpan(new AbsoluteSizeSpan(sp2px(this, 30)), content.indexOf("youku"), ss.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        // 取消下划线
        ss.setSpan(new MyUnderlineSpan(), content.indexOf("youku"), ss.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

        textView.setText(ss);
        textView.setMovementMethod(LinkMovementMethod.getInstance());
    }

// 通过继承UnderlineSpan重写updateDrawState方法setUnderlineText(false)取消下划线
    class MyUnderlineSpan extends  UnderlineSpan{

        @Override
        public void updateDrawState(TextPaint ds) {
            ds.setUnderlineText(false);
        }
    }

    private int sp2px(Context context, float spValue) {
        final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
        return (int) (spValue * fontScale + 0.5f);
    }

UnderLineSpan源码很简单,在updateDrawState设置下划线

public class UnderlineSpan extends CharacterStyle
        implements UpdateAppearance, ParcelableSpan {
    public UnderlineSpan() {
    }

    public UnderlineSpan(Parcel src) {
    }

    public int getSpanTypeId() {
        return TextUtils.UNDERLINE_SPAN;
    }

    public int describeContents() {
        return 0;
    }

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

    @Override
    public void updateDrawState(TextPaint ds) {
        ds.setUnderlineText(true);
    }
}

因此只要继承UnderlineSpan重写下updateDrawState方法即可去掉下划线

    class MyUnderlineSpan extends  UnderlineSpan{

        @Override
        public void updateDrawState(TextPaint ds) {
            ds.setUnderlineText(false);
        }
    }

ClickableSpan源码的话可看到 updateDrawState默认设置带有下划线

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);
    }
}

URLSpan 源码继承于ClickableSpan 并在onClick发起一个意图调用浏览器进行网址的浏览,由于继承于ClickableSpan所以默认带下划线

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 TextUtils.URL_SPAN;
    }

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(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());
        context.startActivity(intent);
    }
}

我们想自己定义webview加载内容的话可以继承URLSpan 进行处理

class MyURLSpan extends URLSpan {
        @Override
        public void onClick(View widget) {
            Uri uri = Uri.parse(getURL());
            // 这里拿到uri进行自己的加载操作即可
            dosomething();
        }
    }

可以看到Spannable是个相当实用的类,想起以前用textview大小颜色或要分开做点击处理的时候,用几个textview拼凑起来就想打自己脸。。。
还有很多属性可以设置,这里就不详细说了,我常用的就这么几个。
讲解完毕,( ^_^ )/~~拜拜

你可能感兴趣的:(Android)