一、效果
二、介绍
2.1 应用场景
现在很多平台要求软件必须有隐私政策弹窗,会有人认为这不就是一段文字嘛,可是仔细看会发现,其中有部分文字会有颜色改变,还有点击事件,这个时候应该怎么办。所以需要使用SpannableString,SpannableStringBuilder。
2.2 介绍
SpannableStringBuilder 有个亲兄弟——SpannableString。是不是觉得有点熟悉?似乎看到了StringBuilder、String的影子…
是的,SpannableStringBuilder和SpannableString的区别类似与StringBuilder、String,就是SpannableStringBuilder可以拼接,而SpannableString不可拼接。
由图中可以看出,他们都实现了CharSequence接口,因此,他们可以直接在TextView的setText中使用。
2.3 主要方法
SpannableStringBuilder和SpannableString主要通过使用 setSpan(Object what, int start, int end, int flags) 改变文本样式。
对应的参数:
- start: 指定Span的开始位置
- end: 指定Span的结束位置,并不包括这个位置。
- flags:取值有如下四个
- Spannable. SPAN_INCLUSIVE_EXCLUSIVE:前面包括,后面不包括,即在文本前插入新的文本会应用该样式,而在文本后插入新文本不会应用该样式
- Spannable. SPAN_INCLUSIVE_INCLUSIVE:前面包括,后面包括,即在文本前插入新的文本会应用该样式,而在文本后插入新文本也会应用该样式
- Spannable. SPAN_EXCLUSIVE_EXCLUSIVE:前面不包括,后面不包括
- Spannable. SPAN_EXCLUSIVE_INCLUSIVE:前面不包括,后面包括
- what: 对应的各种Span,不同的Span对应不同的样式。已知的可用类有:
- BackgroundColorSpan : 文本背景色
- ForegroundColorSpan : 文本颜色
- MaskFilterSpan : 修饰效果,如模糊(BlurMaskFilter)浮雕
- RasterizerSpan : 光栅效果
- StrikethroughSpan : 删除线
- SuggestionSpan : 相当于占位符
- UnderlineSpan : 下划线
- AbsoluteSizeSpan : 文本字体(绝对大小)
- DynamicDrawableSpan : 设置图片,基于文本基线或底部对齐。
- ImageSpan : 图片
- RelativeSizeSpan : 相对大小(文本字体)
- ScaleXSpan : 基于x轴缩放
- StyleSpan : 字体样式:粗体、斜体等
- SubscriptSpan : 下标(数学公式会用到)
- SuperscriptSpan : 上标(数学公式会用到)
- TextAppearanceSpan : 文本外貌(包括字体、大小、样式和颜色)
- TypefaceSpan : 文本字体
- URLSpan : 文本超链接
- ClickableSpan : 点击事件
三、用法
先看布局文件,TextView * 10
3.1 使用ForegroundColorSpan修改字体颜色
- SpannableString – ForegroundColorSpan
- 使用SpannableString修改字体颜色
创建SpannableString的时候,传入需要显示的字符串。使用ForegroundColorSpan为文字设置颜色。
/**
* SpannableString -- ForegroundColorSpan
* 使用SpannableString修改字体颜色
*/
private void test1(){
SpannableString spannableString = new SpannableString("使用SpannableString修改字体颜色");
ForegroundColorSpan span = new ForegroundColorSpan(Color.BLUE);
//坐标前不包括,后面包括
spannableString.setSpan(span,3,17, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
((TextView) findViewById(R.id.test1_tv)).setText(spannableString);
}
效果图:
3.2 使用ForegroundColorSpan修改字体颜色
- SpannableStringBuilder – ForegroundColorSpan
- 使用SpannableStringBuilder修改字体颜色
这里就可以看出SpannableStringBuilder的可拼接性,这里同样采用了ForegroundColorSpan为文本设置颜色。
/**
* SpannableStringBuilder -- ForegroundColorSpan
* 使用SpannableStringBuilder修改字体颜色
*/
private void test2() {
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
spannableStringBuilder.append("使用");
spannableStringBuilder.append("SpannableStringBuilder");
spannableStringBuilder.append("修改字体颜色");
ForegroundColorSpan span = new ForegroundColorSpan(Color.parseColor("#DC143C"));
spannableStringBuilder.setSpan(span,2,24,Spannable.SPAN_INCLUSIVE_INCLUSIVE);
((TextView) findViewById(R.id.test2_tv)).setText(spannableStringBuilder);
// ((TextView) findViewById(R.id.test2_tv)).setTextColor(Color.RED); //使用后会改变全部文字颜色
}
效果图
3.3 使用BackgroundColorSpan设置字体背景颜色
- SpannableStringBuilder – BackgroundColorSpan
- 使用SpannableStringBuilder设置字体背景颜色
使用BackgroundColorSpan设置字体背景颜色
/**
* SpannableStringBuilder -- BackgroundColorSpan
* 使用SpannableStringBuilder设置字体背景颜色
*/
private void test3() {
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
spannableStringBuilder.append("使用SpannableStringBuilder设置字体背景颜色");
BackgroundColorSpan span = new BackgroundColorSpan(Color.GREEN);
spannableStringBuilder.setSpan(span,0,24,Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
((TextView) findViewById(R.id.test3_tv)).setText(spannableStringBuilder);
// ((TextView) findViewById(R.id.test3_tv)).setTextColor(Color.RED); //使用后会改变全部文字颜色
}
效果图
3.4 使用AbsoluteSizeSpan修改字体大小
- SpannableStringBuilder – AbsoluteSizeSpan
- 使用SpannableStringBuilder修改字体大小
使用AbsoluteSizeSpan修改字体大小
/**
* SpannableStringBuilder -- AbsoluteSizeSpan
* 使用SpannableStringBuilder修改字体大小
*/
private void test4() {
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
spannableStringBuilder.append("使用SpannableStringBuilder修改字体大小");
AbsoluteSizeSpan span = new AbsoluteSizeSpan(20);
spannableStringBuilder.setSpan(span,2,24,Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
((TextView) findViewById(R.id.test4_tv)).setText(spannableStringBuilder);
}
效果图
3.5 使用StyleSpan设置文字样式
- SpannableStringBuilder – StyleSpan
- 使用SpannableStringBuilder设置文字样式(粗体、斜体)
使用StyleSpan修改字体颜色
/**
* SpannableStringBuilder -- StyleSpan
* 使用SpannableStringBuilder设置文字样式(粗体、斜体)
*/
private void test5() {
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
spannableStringBuilder.append("使用SpannableStringBuilder设置文字样式(粗体、斜体");
StyleSpan styleSpan1 = new StyleSpan(Typeface.BOLD); //粗体
spannableStringBuilder.setSpan(styleSpan1,0,2,Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
StyleSpan styleSpan2 = new StyleSpan(Typeface.ITALIC); //斜体
spannableStringBuilder.setSpan(styleSpan2,2,24,Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
StyleSpan styleSpan3 = new StyleSpan(Typeface.BOLD_ITALIC);//粗斜体
spannableStringBuilder.setSpan(styleSpan3,24,30,Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
((TextView) findViewById(R.id.test5_tv)).setText(spannableStringBuilder);
}
效果图
3.6 使用StrikethroughSpan给文字设置删除线
- SpannableStringBuilder – StrikethroughSpan
- 使用SpannableStringBuilder给文字设置删除线
使用StrikethroughSpan给文字设置删除线
/**
* SpannableStringBuilder -- StrikethroughSpan
* 使用SpannableStringBuilder给文字设置删除线
*/
private void test6() {
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
spannableStringBuilder.append("使用SpannableStringBuilder给文字设置删除线");
StrikethroughSpan span = new StrikethroughSpan();
spannableStringBuilder.setSpan(span,2,24,Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
((TextView) findViewById(R.id.test6_tv)).setText(spannableStringBuilder);
}
效果图
3.7 使用UnderlineSpan给文字设置下划线
- SpannableStringBuilder – UnderlineSpan
- 使用SpannableStringBuilder给文字设置下划线
使用UnderlineSpan给文字设置下划线
/**
* SpannableStringBuilder -- UnderlineSpan
* 使用SpannableStringBuilder给文字设置下划线
*/
private void test7() {
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
spannableStringBuilder.append("使用SpannableStringBuilder给文字设置下划线");
UnderlineSpan span = new UnderlineSpan();
spannableStringBuilder.setSpan(span,2,24,Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
((TextView) findViewById(R.id.test7_tv)).setText(spannableStringBuilder);
}
效果图
3.8 使用ImageSpan在文字中插入图片
- SpannableStringBuilder – ImageSpan
- 使用SpannableStringBuilder在文字中插入图片
使用ImageSpan在文字中插入图片
/**
* SpannableStringBuilder -- ImageSpan
* 使用SpannableStringBuilder在文字中插入图片
*/
private void test8() {
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
spannableStringBuilder.append("使用SpannableStringBuilder在文字中插入图片");
ImageSpan span = new ImageSpan(this,R.mipmap.ic_launcher);
//也可以这样
//Drawable drawable = getResources().getDrawable(R.mipmap.ic_launcher);
//drawable.setBounds(0,0,drawable.getIntrinsicWidth(),drawable.getIntrinsicHeight());
//ImageSpan span = new ImageSpan(drawable);
//将下标2-24的字符用图片代替
spannableStringBuilder.setSpan(span,2,24,Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
((TextView) findViewById(R.id.test8_tv)).setText(spannableStringBuilder);
}
效果图:
3.9 使用ClickableSpan给文字设置点击事件
- SpannableStringBuilder – ClickableSpan
- 使用SpannableStringBuilder给文字设置点击事件
使用ClickableSpan给文字设置点击事件
/**
* SpannableStringBuilder -- ClickableSpan
* 使用SpannableStringBuilder给文字设置点击事件
*/
private void test9() {
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
spannableStringBuilder.append("使用SpannableStringBuilder给文字设置点击事件");
ClickableSpan span = new ClickableSpan() {
@Override
public void onClick(@NonNull View view) {
Toast.makeText(MainActivity.this,"触发点击事件",Toast.LENGTH_SHORT).show();
}
};
spannableStringBuilder.setSpan(span,2,24,Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
((TextView) findViewById(R.id.test9_tv)).setText(spannableStringBuilder);
((TextView) findViewById(R.id.test9_tv)).setMovementMethod(LinkMovementMethod.getInstance());
}
效果图:
3.10 使用SpannableStringBuilder事件组合使用
/**
* 使用SpannableStringBuilder事件组合使用
*/
private void test10() {
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
spannableStringBuilder.append("使用SpannableStringBuilder事件组合使用");
//图片
ImageSpan imageSpan = new ImageSpan(this,R.mipmap.ic_launcher);
spannableStringBuilder.setSpan(imageSpan,2,24,Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
//点击事件
ClickableSpan clickableSpan = new ClickableSpan() {
@Override
public void onClick(@NonNull View view) {
Toast.makeText(MainActivity.this,"我是点击事件",Toast.LENGTH_SHORT).show();
}
};
spannableStringBuilder.setSpan(clickableSpan,2,24,Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
//文字颜色
ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(Color.RED);
spannableStringBuilder.setSpan(foregroundColorSpan,24,30,Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
//文字背景颜色
BackgroundColorSpan backgroundColorSpan = new BackgroundColorSpan(Color.BLUE);
spannableStringBuilder.setSpan(backgroundColorSpan,24,30,Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
((TextView) findViewById(R.id.test10_tv)).setText(spannableStringBuilder);
((TextView) findViewById(R.id.test10_tv)).setMovementMethod(LinkMovementMethod.getInstance());
}
注意事项: 由于下标为2–24的字符串被图片代替,再设置文字背景颜色和文字颜色不产生效果。
效果图:
四、附录代码
4.1 Activity代码
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
test1(); //使用SpannableString ForegroundColorSpan修改字体颜色
test2(); //使用SpannableStringBuilder ForegroundColorSpan修改字体颜色
test3(); //使用SpannableStringBuilder BackgroundColorSpan设置字体背景颜色
test4(); //使用SpannableStringBuilder AbsoluteSizeSpan修改字体大小
test5(); //使用SpannableStringBuilder StyleSpan设置文字样式(粗体、斜体)
test6(); //使用SpannableStringBuilder StrikethroughSpan给文字设置删除线
test7(); //使用SpannableStringBuilder UnderlineSpan给文字设置下划线
test8(); //使用SpannableStringBuilder ImageSpan在文字中插入图片
test9(); //使用SpannableStringBuilder ClickableSpan给文字设置点击事件
test10(); //使用SpannableStringBuilder事件组合使用
}
/**
* 使用SpannableStringBuilder事件组合使用
*/
private void test10() {
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
spannableStringBuilder.append("使用SpannableStringBuilder事件组合使用");
//图片
ImageSpan imageSpan = new ImageSpan(this,R.mipmap.ic_launcher);
spannableStringBuilder.setSpan(imageSpan,2,24,Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
//点击事件
ClickableSpan clickableSpan = new ClickableSpan() {
@Override
public void onClick(@NonNull View view) {
Toast.makeText(MainActivity.this,"我是点击事件",Toast.LENGTH_SHORT).show();
}
};
spannableStringBuilder.setSpan(clickableSpan,2,24,Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
//文字颜色
ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(Color.RED);
spannableStringBuilder.setSpan(foregroundColorSpan,24,30,Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
//文字背景颜色
BackgroundColorSpan backgroundColorSpan = new BackgroundColorSpan(Color.BLUE);
spannableStringBuilder.setSpan(backgroundColorSpan,24,30,Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
((TextView) findViewById(R.id.test10_tv)).setText(spannableStringBuilder);
((TextView) findViewById(R.id.test10_tv)).setMovementMethod(LinkMovementMethod.getInstance());
}
/**
* SpannableStringBuilder -- ClickableSpan
* 使用SpannableStringBuilder给文字设置点击事件
*/
private void test9() {
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
spannableStringBuilder.append("使用SpannableStringBuilder给文字设置点击事件");
ClickableSpan span = new ClickableSpan() {
@Override
public void onClick(@NonNull View view) {
Toast.makeText(MainActivity.this,"触发点击事件",Toast.LENGTH_SHORT).show();
}
};
spannableStringBuilder.setSpan(span,2,24,Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
((TextView) findViewById(R.id.test9_tv)).setText(spannableStringBuilder);
((TextView) findViewById(R.id.test9_tv)).setMovementMethod(LinkMovementMethod.getInstance());
}
/**
* SpannableStringBuilder -- ImageSpan
* 使用SpannableStringBuilder在文字中插入图片
*/
private void test8() {
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
spannableStringBuilder.append("使用SpannableStringBuilder在文字中插入图片");
ImageSpan span = new ImageSpan(this,R.mipmap.ic_launcher);
//也可以这样
//Drawable drawable = getResources().getDrawable(R.mipmap.ic_launcher);
//drawable.setBounds(0,0,drawable.getIntrinsicWidth(),drawable.getIntrinsicHeight());
//ImageSpan span = new ImageSpan(drawable);
//将下标2-24的字符用图片代替
spannableStringBuilder.setSpan(span,2,24,Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
((TextView) findViewById(R.id.test8_tv)).setText(spannableStringBuilder);
}
/**
* SpannableStringBuilder -- UnderlineSpan
* 使用SpannableStringBuilder给文字设置下划线
*/
private void test7() {
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
spannableStringBuilder.append("使用SpannableStringBuilder给文字设置下划线");
UnderlineSpan span = new UnderlineSpan();
spannableStringBuilder.setSpan(span,2,24,Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
((TextView) findViewById(R.id.test7_tv)).setText(spannableStringBuilder);
}
/**
* SpannableStringBuilder -- StrikethroughSpan
* 使用SpannableStringBuilder给文字设置删除线
*/
private void test6() {
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
spannableStringBuilder.append("使用SpannableStringBuilder给文字设置删除线");
StrikethroughSpan span = new StrikethroughSpan();
spannableStringBuilder.setSpan(span,2,24,Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
((TextView) findViewById(R.id.test6_tv)).setText(spannableStringBuilder);
}
/**
* SpannableStringBuilder -- StyleSpan
* 使用SpannableStringBuilder设置文字样式(粗体、斜体)
*/
private void test5() {
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
spannableStringBuilder.append("使用SpannableStringBuilder设置文字样式(粗体、斜体");
StyleSpan styleSpan1 = new StyleSpan(Typeface.BOLD); //粗体
spannableStringBuilder.setSpan(styleSpan1,0,2,Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
StyleSpan styleSpan2 = new StyleSpan(Typeface.ITALIC); //斜体
spannableStringBuilder.setSpan(styleSpan2,2,24,Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
StyleSpan styleSpan3 = new StyleSpan(Typeface.BOLD_ITALIC);//粗斜体
spannableStringBuilder.setSpan(styleSpan3,24,30,Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
((TextView) findViewById(R.id.test5_tv)).setText(spannableStringBuilder);
}
/**
* SpannableStringBuilder -- AbsoluteSizeSpan
* 使用SpannableStringBuilder修改字体大小
*/
private void test4() {
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
spannableStringBuilder.append("使用SpannableStringBuilder修改字体大小");
AbsoluteSizeSpan span = new AbsoluteSizeSpan(20);
spannableStringBuilder.setSpan(span,2,24,Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
((TextView) findViewById(R.id.test4_tv)).setText(spannableStringBuilder);
}
/**
* SpannableStringBuilder -- BackgroundColorSpan
* 使用SpannableStringBuilder设置字体背景颜色
*/
private void test3() {
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
spannableStringBuilder.append("使用SpannableStringBuilder设置字体背景颜色");
BackgroundColorSpan span = new BackgroundColorSpan(Color.GREEN);
spannableStringBuilder.setSpan(span,0,24,Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
((TextView) findViewById(R.id.test3_tv)).setText(spannableStringBuilder);
// ((TextView) findViewById(R.id.test3_tv)).setTextColor(Color.RED); //使用后会改变全部文字颜色
}
/**
* SpannableStringBuilder -- ForegroundColorSpan
* 使用SpannableStringBuilder修改字体颜色
*/
private void test2() {
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
spannableStringBuilder.append("使用");
spannableStringBuilder.append("SpannableStringBuilder");
spannableStringBuilder.append("修改字体颜色");
ForegroundColorSpan span = new ForegroundColorSpan(Color.parseColor("#DC143C"));
spannableStringBuilder.setSpan(span,2,24,Spannable.SPAN_INCLUSIVE_INCLUSIVE);
((TextView) findViewById(R.id.test2_tv)).setText(spannableStringBuilder);
// ((TextView) findViewById(R.id.test2_tv)).setTextColor(Color.RED); //使用后会改变全部文字颜色
}
/**
* SpannableString -- ForegroundColorSpan
* 使用SpannableString修改字体颜色
*/
private void test1(){
SpannableString spannableString = new SpannableString("使用SpannableString修改字体颜色");
ForegroundColorSpan span = new ForegroundColorSpan(Color.BLUE);
spannableString.setSpan(span,3,17, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
((TextView) findViewById(R.id.test1_tv)).setText(spannableString);
}
}
4.2 XML代码
<?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=".MainActivity">
<TextView
android:id="@+id/test1_tv"
style="@style/tvStyle"/>
<TextView
android:id="@+id/test2_tv"
style="@style/tvStyle"/>
<TextView
android:id="@+id/test3_tv"
style="@style/tvStyle"/>
<TextView
android:id="@+id/test4_tv"
style="@style/tvStyle"/>
<TextView
android:id="@+id/test5_tv"
style="@style/tvStyle"/>
<TextView
android:id="@+id/test6_tv"
style="@style/tvStyle"/>
<TextView
android:id="@+id/test7_tv"
style="@style/tvStyle"/>
<TextView
android:id="@+id/test8_tv"
style="@style/tvStyle"/>
<TextView
android:id="@+id/test9_tv"
style="@style/tvStyle"/>
<TextView
android:id="@+id/test10_tv"
style="@style/tvStyle"/>
</LinearLayout>
4.3 Style代码
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="tvStyle">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:gravity">center</item>
<item name="android:padding">10dp</item>
<item name="android:text">Hello World!</item>
</style>
</resources>
以上就是所有学习内容,记录一下方便以后复习, over