美文网首页嵌牛IT观察
给TextView插上SpannableString的翅膀

给TextView插上SpannableString的翅膀

作者: 连嘉玮 | 来源:发表于2017-12-13 09:47 被阅读0次

    姓名 连嘉玮 学号 16040120089

    转自:http://www.jianshu.com/p/b5fb51529d06?utm_campaign=hugo&utm_medium=reader_share&utm_content=note&utm_source=qq

    有删节

    【嵌牛导读】:TextView通过设置SpannableString后功能就异常强大了,在自定义的Span的情况下,可以说就要上天了。

    【嵌牛鼻子】:部分文本变色,商城打折的删除线,粗体,斜体,不同大小的文字,文字混合表情,文字点击链接

    【嵌牛提问】:如何设计编写这些特征?

    【嵌牛正文】:

    SpannableString(标签文本),可以用来显示复合文本,我们可以通过SpannableString给文本设置各种各样的样式。比如部分文本变色,商城打折的删除线,粗体,斜体,不同大小的文字,文字混合表情,文字点击链接等。TextView通过设置SpannableString后功能就异常强大了,在自定义的Span的情况下,可以说就要上天了。

    完整代码请戳github代码直通车

    认识SpannableString:

    在TextView的public final void setText(CharSequence text)方法中,设置文本,那么这个我们每天都要用的CharSequence到底是什么呢?看Google的官方文档:

    image.png

    SpannableString继承于CharSequence,所以通过textView.setText(spannableString)的方式使用。SpannableString构造方法参数传入需要设置样式的文本。

    public void setSpan(Object what, int start, int end, int flags)

    what为各种类型Span,start为起始位置,end为结束位置,flags为开闭区间的标致。

    flags类型:

    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE 开开区间,如(0,1)

    Spanned.SPAN_INCLUSIVE_EXCLUSIVE 闭开区间,如[0,1)

    Spanned.SPAN_EXCLUSIVE_INCLUSIVE 开闭区间,如(0,1]

    Spanned.SPAN_INCLUSIVE_INCLUSIVE 闭闭区间,如[0,1]

    使用步骤:

    创建SpannableString,构造方法设置文本

    创建Span,SpannableString.setSpan()

    textView.setText(spannableString)

    ForegroundColorSpan 设置文字前景色(文字颜色)

    image.png

        public static SpannableString getForegroundColorSpan(Context context){

            SpannableString spannableString = new SpannableString("我已同意抖音使用协议");

            ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(context.getResources().getColor(R.color.colorPrimary));

            spannableString.setSpan(foregroundColorSpan,4,spannableString.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);

            return spannableString;

        }

    BackgroundColorSpan 设置文字背景色

    image.png

        public static SpannableString getBackgroundColorSpan(Context context){

            SpannableString spannableString = new SpannableString("你看我头像牛逼不?");

            BackgroundColorSpan backgroundColorSpan = new BackgroundColorSpan(context.getResources().getColor(R.color.colorAccent));

            spannableString.setSpan(backgroundColorSpan,3,5,Spanned.SPAN_INCLUSIVE_INCLUSIVE);

            return spannableString;

        }

    StrikethroughSpan 设置删除线

    image.png

        public static SpannableString getStrikethroughSpan(){

            SpannableString spannableString = new SpannableString("尤龙的传人");

            StrikethroughSpan strikethroughSpan = new StrikethroughSpan();

            spannableString.setSpan(strikethroughSpan,0,1,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            return spannableString;

        }

    UnderlineSpan 设置下划线

    image.png

        public static SpannableString getUnderlineSpan(){

            SpannableString spannableString = new SpannableString("这里是下划线");

            UnderlineSpan underlineSpan = new UnderlineSpan();

            spannableString.setSpan(underlineSpan,3,6,Spanned.SPAN_INCLUSIVE_INCLUSIVE);

            return spannableString;

        }

    ScaleXSpan 设置X轴方向拉伸,ScaleXSpan构造方法参数传缩放倍数

    image.png

        public static SpannableString getScaleXSpan(){

            SpannableString spannableString = new SpannableString("媳妇你长胖了");

            ScaleXSpan scaleXSpan = new ScaleXSpan(2);

            spannableString.setSpan(scaleXSpan,0,spannableString.length(),Spanned.SPAN_INCLUSIVE_INCLUSIVE);

            return spannableString;

        }

    RelativeSizeSpan 设置文字比例大小,原文字大小基数为1,构造函数参数为float值,缩放为原来比例,给文字依序设置不同大小。

    image.png

        public static SpannableString getRelativeSizeSpan(){

            SpannableString spannableString = new SpannableString("我心情忐忑不安七上八下");

            RelativeSizeSpan sizeSpan1 = new RelativeSizeSpan(1.2f);

            RelativeSizeSpan sizeSpan2 = new RelativeSizeSpan(1.4f);

            RelativeSizeSpan sizeSpan3 = new RelativeSizeSpan(1.6f);

            RelativeSizeSpan sizeSpan4 = new RelativeSizeSpan(1.8f);

            spannableString.setSpan(sizeSpan1,0,1,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            spannableString.setSpan(sizeSpan2,1,2,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            spannableString.setSpan(sizeSpan3,2,3,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            spannableString.setSpan(sizeSpan4,3,4,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            spannableString.setSpan(sizeSpan3,4,5,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            spannableString.setSpan(sizeSpan2,5,6,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            spannableString.setSpan(sizeSpan1,6,7,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            spannableString.setSpan(sizeSpan2,7,8,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            spannableString.setSpan(sizeSpan3,8,9,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            spannableString.setSpan(sizeSpan4,9,10,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            return spannableString;

        }

    SuperscriptSpan 设置上标,给平方这个2设置为上标,并且文字缩小。当然这个在望京买套房是我奢侈的梦想。

    image.png

        public static SpannableString getSuperscriptSpan(){

            SpannableString spannableString = new SpannableString("刚在北京望京买了套1202m的房子");

            SuperscriptSpan superscriptSpan = new SuperscriptSpan();

            RelativeSizeSpan sizeSpan = new RelativeSizeSpan(0.7f);

            spannableString.setSpan(superscriptSpan,12,13,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            spannableString.setSpan(sizeSpan,12,13,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            return spannableString;

        }

    SubscriptSpan设置下标,给这个2设置为下标并缩小。

    image.png

        public static SpannableString getSubscriptSpan(){

            SpannableString spannableString = new SpannableString("水分子化学式为H20");

            SubscriptSpan subscriptSpan = new SubscriptSpan();

            RelativeSizeSpan sizeSpan = new RelativeSizeSpan(0.7f);

            spannableString.setSpan(subscriptSpan,8,9,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            spannableString.setSpan(sizeSpan,8,9,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            return spannableString;

        }

    StyleSpan设置粗体、斜体样式:Typeface.BOLD为粗体字,Typeface.ITALIC为斜体字类型。

    image.png

        public static SpannableString getStyleSpan(){

            SpannableString spannableString = new SpannableString("身正不怕影子歪");

            StyleSpan styleSpanBold = new StyleSpan(Typeface.BOLD);

            StyleSpan styleSpanitalic = new StyleSpan(Typeface.ITALIC);

            spannableString.setSpan(styleSpanBold,0,4,Spanned.SPAN_INCLUSIVE_INCLUSIVE);

            spannableString.setSpan(styleSpanitalic,4,6,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            return spannableString;

        }

    ImageSpan 图文混合,比如在聊天中带有表情图标。这个是文字替换功能,将对应位置的字符替换为图标,这里将文本的空格替换为fx图标;drawable.setBounds()可设置图标的大小。

    image.png

        public static SpannableString getImageSpan(Context context){

            SpannableString spannableString = new SpannableString("芭芭拉小魔仙 魔法棒");

            Drawable drawable = context.getResources().getDrawable(R.mipmap.fx);

            drawable.setBounds(0,0,70,70);

            ImageSpan imageSpan = new ImageSpan(drawable);

            spannableString.setSpan(imageSpan,6,7,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            return spannableString;

        }

    ClickableSpan可点击标签,textview需设置:红色带下滑先的“哪里”,就是可点击范围,ClickableSpan自带点击回调。

    giphy (1).gif

    tvClick.setMovementMethod(LinkMovementMethod.getInstance())方法,textview才会响应点击事件

        public static SpannableString getClickableSpan(final Context context){

            SpannableString spannableString = new SpannableString("哪里不会点哪里,so easy!");

            ClickableSpan clickableSpan = new ClickableSpan() {

                @Override

                public void onClick(View widget) {

                    Toast.makeText(context,"你戳中我了",Toast.LENGTH_SHORT).show();

                }

            };

            spannableString.setSpan(clickableSpan,5,7,Spanned.SPAN_INCLUSIVE_INCLUSIVE);

            return spannableString;

        }

    URLSpan跳转链接,可以设置为打电话,发短信,发邮件,打开网页等功能;类似于Intent的打电话,发短信,发邮件,打开网页的功能。

    giphy.gif

        public static SpannableString getURLSpan(){

            SpannableString spannableString = new SpannableString("打电话,发短信,发邮件,打开网页");

            spannableString.setSpan(new URLSpan("tel:10086"), 0, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

            spannableString.setSpan(new URLSpan("smsto:10086"), 4, 7, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

            spannableString.setSpan(new URLSpan("mailto:88888888@qq.com"), 8, 11, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

            spannableString.setSpan(new URLSpan("http://www.jianshu.com"), 12, 16, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

            return spannableString;

        }

    完整SpanUtils样式类:

    import android.content.Context;

    import android.graphics.Typeface;

    import android.graphics.drawable.Drawable;

    import android.text.SpannableString;

    import android.text.Spanned;

    import android.text.style.BackgroundColorSpan;

    import android.text.style.ClickableSpan;

    import android.text.style.ForegroundColorSpan;

    import android.text.style.ImageSpan;

    import android.text.style.RelativeSizeSpan;

    import android.text.style.ScaleXSpan;

    import android.text.style.StrikethroughSpan;

    import android.text.style.StyleSpan;

    import android.text.style.SubscriptSpan;

    import android.text.style.SuperscriptSpan;

    import android.text.style.URLSpan;

    import android.text.style.UnderlineSpan;

    import android.view.View;

    import android.widget.Toast;

    /**

    * Created by libo on 2017/12/12.

    */

    public class SpanUtils {

        public static SpannableString getForegroundColorSpan(Context context){

            SpannableString spannableString = new SpannableString("我已同意抖音使用协议");

            ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(context.getResources().getColor(R.color.colorPrimary));

            spannableString.setSpan(foregroundColorSpan,4,spannableString.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);

            return spannableString;

        }

        public static SpannableString getBackgroundColorSpan(Context context){

            SpannableString spannableString = new SpannableString("你看我头像牛逼不?");

            BackgroundColorSpan backgroundColorSpan = new BackgroundColorSpan(context.getResources().getColor(R.color.colorAccent));

            spannableString.setSpan(backgroundColorSpan,3,5,Spanned.SPAN_INCLUSIVE_INCLUSIVE);

            return spannableString;

        }

        public static SpannableString getStrikethroughSpan(){

            SpannableString spannableString = new SpannableString("尤龙的传人");

            StrikethroughSpan strikethroughSpan = new StrikethroughSpan();

            spannableString.setSpan(strikethroughSpan,0,1,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            return spannableString;

        }

        public static SpannableString getUnderlineSpan(){

            SpannableString spannableString = new SpannableString("这里是下划线");

            UnderlineSpan underlineSpan = new UnderlineSpan();

            spannableString.setSpan(underlineSpan,3,6,Spanned.SPAN_INCLUSIVE_INCLUSIVE);

            return spannableString;

        }

        public static SpannableString getScaleXSpan(){

            SpannableString spannableString = new SpannableString("媳妇你长胖了");

            ScaleXSpan scaleXSpan = new ScaleXSpan(2);

            spannableString.setSpan(scaleXSpan,0,spannableString.length(),Spanned.SPAN_INCLUSIVE_INCLUSIVE);

            return spannableString;

        }

        public static SpannableString getSuperscriptSpan(){

            SpannableString spannableString = new SpannableString("刚在北京望京买了套1202m的房子");

            SuperscriptSpan superscriptSpan = new SuperscriptSpan();

            RelativeSizeSpan sizeSpan = new RelativeSizeSpan(0.7f);

            spannableString.setSpan(superscriptSpan,12,13,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            spannableString.setSpan(sizeSpan,12,13,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            return spannableString;

        }

        public static SpannableString getSubscriptSpan(){

            SpannableString spannableString = new SpannableString("水分子化学式为H20");

            SubscriptSpan subscriptSpan = new SubscriptSpan();

            RelativeSizeSpan sizeSpan = new RelativeSizeSpan(0.7f);

            spannableString.setSpan(subscriptSpan,8,9,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            spannableString.setSpan(sizeSpan,8,9,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            return spannableString;

        }

        public static SpannableString getStyleSpan(){

            SpannableString spannableString = new SpannableString("身正不怕影子歪");

            StyleSpan styleSpanBold = new StyleSpan(Typeface.BOLD);

            StyleSpan styleSpanitalic = new StyleSpan(Typeface.ITALIC);

            spannableString.setSpan(styleSpanBold,0,4,Spanned.SPAN_INCLUSIVE_INCLUSIVE);

            spannableString.setSpan(styleSpanitalic,4,6,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            return spannableString;

        }

        public static SpannableString getRelativeSizeSpan(){

            SpannableString spannableString = new SpannableString("我心情忐忑不安七上八下");

            RelativeSizeSpan sizeSpan1 = new RelativeSizeSpan(1.2f);

            RelativeSizeSpan sizeSpan2 = new RelativeSizeSpan(1.4f);

            RelativeSizeSpan sizeSpan3 = new RelativeSizeSpan(1.6f);

            RelativeSizeSpan sizeSpan4 = new RelativeSizeSpan(1.8f);

            spannableString.setSpan(sizeSpan1,0,1,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            spannableString.setSpan(sizeSpan2,1,2,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            spannableString.setSpan(sizeSpan3,2,3,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            spannableString.setSpan(sizeSpan4,3,4,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            spannableString.setSpan(sizeSpan3,4,5,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            spannableString.setSpan(sizeSpan2,5,6,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            spannableString.setSpan(sizeSpan1,6,7,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            spannableString.setSpan(sizeSpan2,7,8,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            spannableString.setSpan(sizeSpan3,8,9,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            spannableString.setSpan(sizeSpan4,9,10,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            return spannableString;

        }

        public static SpannableString getImageSpan(Context context){

            SpannableString spannableString = new SpannableString("芭芭拉小魔仙 魔法棒");

            Drawable drawable = context.getResources().getDrawable(R.mipmap.fx);

            drawable.setBounds(0,0,70,70);

            ImageSpan imageSpan = new ImageSpan(drawable);

            spannableString.setSpan(imageSpan,6,7,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

            return spannableString;

        }

        public static SpannableString getClickableSpan(final Context context){

            SpannableString spannableString = new SpannableString("哪里不会点哪里,so easy!");

            ClickableSpan clickableSpan = new ClickableSpan() {

                @Override

                public void onClick(View widget) {

                    Toast.makeText(context,"你戳中我了",Toast.LENGTH_SHORT).show();

                }

            };

            spannableString.setSpan(clickableSpan,5,7,Spanned.SPAN_INCLUSIVE_INCLUSIVE);

            return spannableString;

        }

        public static SpannableString getURLSpan(){

            SpannableString spannableString = new SpannableString("打电话,发短信,发邮件,打开网页");

            spannableString.setSpan(new URLSpan("tel:10086"), 0, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

            spannableString.setSpan(new URLSpan("smsto:10086"), 4, 7, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

            spannableString.setSpan(new URLSpan("mailto:88888888@qq.com"), 8, 11, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

            spannableString.setSpan(new URLSpan("http://www.jianshu.com"), 12, 16, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

            return spannableString;

        }

    }

    MainActivity完整代码:

    import android.os.Bundle;

    import android.support.v7.app.AppCompatActivity;

    import android.text.method.LinkMovementMethod;

    import android.widget.TextView;

    import butterknife.Bind;

    import butterknife.ButterKnife;

    public class MainActivity extends AppCompatActivity {

        @Bind(R.id.tv_foreground)

        TextView tvForeground;

        @Bind(R.id.tv_background)

        TextView tvBackground;

        @Bind(R.id.tv_relativesize)

        TextView tvRelativesize;

        @Bind(R.id.tv_strikethrough)

        TextView tvStrikethrough;

        @Bind(R.id.tv_underline)

        TextView tvUnderline;

        @Bind(R.id.tv_superscript)

        TextView tvSuperscript;

        @Bind(R.id.tv_subscript)

        TextView tvSubscript;

        @Bind(R.id.tv_style)

        TextView tvStyle;

        @Bind(R.id.tv_image)

        TextView tvImage;

        @Bind(R.id.tv_click)

        TextView tvClick;

        @Bind(R.id.tv_url)

        TextView tvUrl;

        @Bind(R.id.tv_scalex)

        TextView tvScalex;

        @Override

        protected void onCreate(Bundle savedInstanceState) {

            super.onCreate(savedInstanceState);

            setContentView(R.layout.activity_main);

            ButterKnife.bind(this);

            tvForeground.setText(SpanUtils.getForegroundColorSpan(getApplicationContext()));

            tvBackground.setText(SpanUtils.getBackgroundColorSpan(getApplicationContext()));

            tvStrikethrough.setText(SpanUtils.getStrikethroughSpan());

            tvUnderline.setText(SpanUtils.getUnderlineSpan());

            tvScalex.setText(SpanUtils.getScaleXSpan());

            tvSuperscript.setText(SpanUtils.getSuperscriptSpan());

            tvSubscript.setText(SpanUtils.getSubscriptSpan());

            tvStyle.setText(SpanUtils.getStyleSpan());

            tvRelativesize.setText(SpanUtils.getRelativeSizeSpan());

            tvImage.setText(SpanUtils.getImageSpan(getApplicationContext()));

            tvClick.setMovementMethod(LinkMovementMethod.getInstance());  //否则点击没反应

            tvClick.setText(SpanUtils.getClickableSpan(getApplicationContext()));

            tvUrl.setMovementMethod(LinkMovementMethod.getInstance());

            tvUrl.setText(SpanUtils.getURLSpan());

        }

    }

    文章只是讲解单一,组合拳威力更大,系列下一篇会讲自定义Span开发更炫酷的效果。

    相关文章

      网友评论

        本文标题:给TextView插上SpannableString的翅膀

        本文链接:https://www.haomeiwen.com/subject/igfaixtx.html