Span 介绍及使用(二)

上一节介绍了一下Span,有些乱,这一节我们来讲讲Android 提供的各种Span的应用。

使用 Span 的步骤

  1. 定义你要显示的文本
  2. 定义你需要的Span
  3. 使用将要显示文字,构造一个SpannableString
  4. 调用SpannableStringsetSpan()方法设置spansetSpan()的参数会有设置文字的范围。
  5. 调用TextViewsetText()方法,显示SpannableString

修改字符文本格式时使用的CharacterStyle

当我们遇到在布局里无法处理的文本格式,我们就可以使用CharacterStyle

ClickableSpan:可设置文本局部点击,局部文字的颜色

ClickableSpan 同时继承了CharacterStyle和实现了UpdateAppearance

这个Span是第一节开头提到的问题的最好解决方式。
按照上面的步骤我们来使用 ClickableSpan实现局部点击,并且使点击的文字变色

    //1.定义需要显示的文字;使“《协议》”变色,并且给“《协议》”添加点击事件,
    final String protocol = "我已阅读并同意本《协议》";
    //2.定义你需要的`Span`
    ClickableSpan clickableSpan = new ClickableSpan() {
        @Override
        public void onClick(View widget) { // 在这里实现点击事件
             showToast(protocol);
        }
    };
    //3.使用将要显示文字,构造一个`SpannableString`
    SpannableString spannableString = new SpannableString(protocol);
    //4.调用`SpannableString`的`setSpan()`方法设置`span`;`setSpan()`的参数会有设置文字的范围。
    int start = protocol.length() - 4;
    int end = protocol.length();
    spannableString.setSpan(new CustomClickableSpan(protocol), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    //5.调用`TextView`的`setText()`方法,显示`SpannableString`
    mTextView.setText(spannableString);

    //6.这里比平常的Span多一步,要设置一下超链接,否则不会生效
    mTextView.setMovementMethod(LinkMovementMethod.getInstance());

效果图如下:
Span 介绍及使用(二)_第1张图片

虽然上面实现了基本的点击功能,但是美工”《协议》”这两个字的颜色是蓝色,而且不想要下划线;所以还要进一步处理,这就需要看看ClickableSpan的内部是如何处理文字颜色了。它的源码如下:

public abstract class ClickableSpan extends CharacterStyle implements UpdateAppearance {
    public abstract void onClick(View widget);
    @Override
    public void updateDrawState(TextPaint ds) {
        ds.setColor(ds.linkColor);
        ds.setUnderlineText(true);
    }
}

上面的代码显示,它在updateDrawState()方法里面,设置里字体的颜色和下划线。所以我们需要继承ClickableSpan重写一下这个方法,在这个方法里面,设置我们希望的颜色。代码如下:

private class CustomClickableSpan extends ClickableSpan {
    private String msg;
    public CustomClickableSpan(String msg) {
        this.msg = msg;
    }
    @Override
    public void onClick(View widget) {
        showToast(msg);
    }
    @Override
    public void updateDrawState(TextPaint ds) {//在这里设置需要的颜色和是否需要下滑线
        ds.setColor(getResources().getColor(R.color.color_blue));
        ds.setUnderlineText(false);
    }
}

我可以替换之前的第四步:

//4.调用`SpannableString`的`setSpan()`方法设置`span`;`setSpan()`的参数会有设置文字的范围。
int start = protocol.length() - 4;
int end = protocol.length();
spannableString.setSpan(new CustomClickableSpan(protocol), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

效果图如下:
Span 介绍及使用(二)_第2张图片
这样就更换了颜色,去掉了下划线。

实现了TextView局部点击的问题,我们来说说其它的Span

AlignmentSpan.Standard 实现文字的左/右对齐,居中对齐

TextView 文字的对齐方式有三种,对应的是Layout.Alignment中的三个枚举常量

  1. TextView 默认是左对齐的,对应的参数是 Layout.Alignment.ALIGN_NORMAL
  2. 右对齐,即跟默认相反,对应的参数是 Layout.Alignment.ALIGN_OPPOSITE
  3. 居中对齐的,对应的参数是 Layout.Alignment.ALIGN_CENTER

下面我们按照最开始的步骤一步一步设置Span

    //1.定义需要显示的文字
    String text = "Sometimes I really doubt whether there is love between my parents. " +
            "Every day they are very busy trying to earn money in order to pay the high tuition for my brother and me. " +
            "They don't act in the romantic ways that I read in books or I see on TV.";
    //2.定义你需要的`Span`
    AlignmentSpan.Standard alignmentSpan = new AlignmentSpan.Standard(Layout.Alignment.ALIGN_OPPOSITE);
    //3.使用将要显示文字,构造一个`SpannableString`
    SpannableString spannableString = new SpannableString(text);
    //4.调用`SpannableString`的`setSpan()`方法设置`span`;`setSpan()`的参数会有设置文字的范围。
    spannableString.setSpan(alignmentSpan, 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    //5.调用`TextView`的`setText()`方法,显示`SpannableString`
    mTextView.setText(spannableString);

这里设置文字的对齐方式,是作用到段落上的,所以在设置 start 和 end 范围时要注意,设置几个范围的内的字符,是没有反应得。

上面代码的效果如图所示:

如果要实现居中对齐可在第2步定义Span的时候,把参数设置成 Layout.Alignment.ALIGN_CENTER

UnderlineSpan 实现文字下划线的功能

我们这里如要给TextView的文字加上下划线,只需要重复上面的5个步骤,并且替换第2步就Ok了。

//2.定义你需要的`Span`
UnderlineSpan underlineSpan = new UnderlineSpan();

然后把它UnderlineSpan的引用传给SpannableStringsetSpan()方法就Ok了。

StrikethroughSpan 实现删除线 功能

同样我只需要将定义 StrikethroughSpan ,然后将其引用传递给SpannableStringsetSpan()方法就Ok了。

//2.定义你需要的`Span`
StrikethroughSpan strikethroughSpan = new StrikethroughSpan();

以下如果没有特殊说明,我们都是重复上面的步骤,只是修改了第二步。

ImageSpan 替换指定位置跟指定长度的字符

//2.定义你需要的`Span`
ImageSpan imageSpan = new ImageSpan(this,R.drawable.ic_launcher);
//……省略第3步
//4.这里会把从20-30的字符替换为图片
spannableString.setSpan(imageSpan, 20, 30, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

ImageSpan 还有多个构造方法,主要还有传入BitmapDrawable

SubscriptSpan 把字符变成下标

     //2.定义你需要的`Span`
    SubscriptSpan span = new SubscriptSpan();
    //3.使用将要显示文字,构造一个`SpannableString`
    SpannableString spannableString = new SpannableString(text);
    //4.将第19到第24个字符设成下标
    spannableString.setSpan(span, 19, 24, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

效果图如下:

SuperscriptSpan 把字符变成上角标

    //2.定义你需要的`Span`
    SuperscriptSpan  span = new SuperscriptSpan ();
    //3.使用将要显示文字,构造一个`SpannableString`
    SpannableString spannableString = new SpannableString(text);
    //4.将第19到第24个字符设成上角标
    spannableString.setSpan(span, 19, 24, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

效果图如下:
Span 介绍及使用(二)_第3张图片

StyleSpan 设置文字的样式

StyleSpan 设置的内容相当于在 布局 里设置 android:textStyle

//2.定义一个StyleSpan,并且设置 文字为粗体
StyleSpan  span = new StyleSpan(Typeface.BOLD);

除了粗体,还有其它风格:
ITALIC 斜体
BOLD_ITALIC 粗斜体

TextView 默认的格式 NORMAL

TypefaceSpan 设置文字的文体,

参数为Android内置的文字字体家族。包含”normal”,”sans”,”serif”,”monospace”,”sans-serif-light” 等

//2.定义你需要的`Span`
TypefaceSpan  span = new TypefaceSpan("serif");

TextAppearanceSpan 可以在 style文件里自定义文字的风格

//2.定义你需要的`Span`
TextAppearanceSpan   span = new TextAppearanceSpan (this,R.style.TextAppearanceSpan);

RelativeSizeSpan 设置指定文字相对于其它文字的大小

//2.这里设置的是指定范围内的文字是其他文字大小的2倍
RelativeSizeSpan relativeSizeSpan = new RelativeSizeSpan(2.0f);

相对的还有 AbsoluteSizeSpan,这个指定是文字的绝对大小,参数设置的是绝对的大小

//2.设置文字的绝对大小,并且设置单位为 dip
AbsoluteSizeSpan span = new AbsoluteSizeSpan(24, true);

ScaleXSpan 设置指定文字 在 x 轴方向缩放的大小

//2横向放大2倍;横向缩小应该小于 1.0f。
ScaleXSpan scaleXSpan = new ScaleXSpan(2.0f); 

还剩下几个 Span,大家可自己尝试一下,看看能出现什么效果。

另外 在这行代码中

spannableString.setSpan(imageSpan, 20, 30, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

最后一个参数,会在获取字符长度时用到。这里用到的是 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE,表示不包含start位置的字符也不含end位置的字符。除了这个还有其他三个参数:

Spanned.SPAN_INCLUSIVE_EXCLUSIVE(包括start,不包括end)
Spanned.SPAN_EXCLUSIVE_INCLUSIVE(不包括start,包括end)
Spanned.SPAN_INCLUSIVE_INCLUSIVE(start、end 都包括)。

你可能感兴趣的:(android,textview,span)