使用TextView的过程中,有时候会需要将一串文本中的部分文字做特别的显示效果处理,比如加粗、改变颜色、加着重标识、超链接等等,我们可以通过多个TextView拼凑来实现,但如果需要特殊处理的内容在整个文本的中间,用多个TextView拼凑实在是太麻烦了,Android提供的SpannableString类能够很好地解决这个问题,SpannableString结合下面各种以Span结尾的类可以做出丰富多样的显示效果。
这里重点要理解的是setSpan方法:
第一个参数对应的是一个相应的Span对象,比如颜色的Span对象,图片的Span对象都是不同的。
第二个参数是开始设置的字符串的游标值
第三个参数是设置末尾的字符串的游标值
第四个参数是代表一个标识,一般使用固定的就可以了。
还有一个就是一个SpannableString对象是可以通过setSpan方法设置多个Span对象的。
最后把SpannableString对象当成一个String字符串通过SetText方法传给TextView,就完成所有的操作了。
一.SpannableString的基本使用代码示例:
//设置Url地址连接
private void addUrlSpan() {
SpannableString spanString = new SpannableString("超链接");
URLSpan span = new URLSpan("tel:0123456789");
spanString.setSpan(span, 0, 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.append(spanString);
}
//设置字体背景的颜色
private void addBackColorSpan() {
SpannableString spanString = new SpannableString("文字背景颜色");
BackgroundColorSpan span = new BackgroundColorSpan(Color.YELLOW);
spanString.setSpan(span, 0, 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.append(spanString);
}
//设置字体的颜色
private void addForeColorSpan() {
SpannableString spanString = new SpannableString("文字前景颜色");
ForegroundColorSpan span = new ForegroundColorSpan(Color.BLUE);
spanString.setSpan(span, 0, 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.append(spanString);
}
//设置字体的大小
private void addFontSpan() {
SpannableString spanString = new SpannableString("36号字体");
AbsoluteSizeSpan span = new AbsoluteSizeSpan(36);
spanString.setSpan(span, 0, 5, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.append(spanString);
}
//设置字体加粗
private void addStyleSpan() {
SpannableString spanString = new SpannableString("BIBI");
StyleSpan span = new StyleSpan(Typeface.BOLD_ITALIC);//加粗
spanString.setSpan(span, 0, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.append(spanString);
}
//给字体中间添加删除线
private void addStrikeSpan() {
SpannableString spanString = new SpannableString("删除线");
StrikethroughSpan span = new StrikethroughSpan();
spanString.setSpan(span, 0, 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.append(spanString);
}
//给字体添加下划线
private void addUnderLineSpan() {
SpannableString spanString = new SpannableString("下划线");
UnderlineSpan span = new UnderlineSpan();
spanString.setSpan(span, 0, 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.append(spanString);
}
//给TextView添加图片
private void addImageSpan() {
SpannableString spanString = new SpannableString(" ");
Drawable d = getResources().getDrawable(R.drawable.ic_launcher);
d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BASELINE);
spanString.setSpan(span, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.append(spanString);
}
}
上面都是比较零碎的使用,下面简单演示一个使用的示例。
二.SpannableString使用示例
程序运行效果:
上面是一个字符串,前面添加一个一个图像,中间改变一些字体的背景颜色和字体本身的颜色,最后超链接,点击超链接文本可以跳转到指定的网页。
程序设计代码:
(一)主布局文件activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.newa.MainActivity" >
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
</RelativeLayout>
比较简单就一个TextView。
(二)activity_web.xml超链接显示的界面的布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="@+id/main_wv"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:onClick="toback"
android:text="回退网页" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:onClick="topre"
android:text="前一网页" />
</RelativeLayout>
(三)主方法的类
package com.example.newa;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.method.LinkMovementMethod;
import android.text.style.BackgroundColorSpan;
import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.ImageSpan;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//显示的字符串
String str = " 这是设置TextView部分文字背景颜色和前景颜色的demo!可以点击连接的地址:我的博客";
int bstart = str.indexOf("背景");
int bend = bstart + "背景".length();
int fstart = str.indexOf("前景");
int fend = fstart + "前景".length();
int baidustart = str.indexOf("我的博客");
int baiduend = baidustart + "我的博客".length();
//创建SpannableString对象,要传入字符串对象
SpannableString style = new SpannableString(str);
//设置多个Span对象
style.setSpan(new BackgroundColorSpan(Color.RED), bstart, bend,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
style.setSpan(new ForegroundColorSpan(Color.RED), fstart, fend,
Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
//设置超链接Span对象的自定义设置
style.setSpan(new ClickableSpan() {
// 在onClick方法中,指向
@Override
public void onClick(View widget) {
Log.e("TAG", "你点击到我了");
// 页面的跳转
Intent intent = new Intent(MainActivity.this, WebActivity.class);
intent.putExtra("url",
"http://blog.csdn.net/wenzhi20102321?viewmode=list");
startActivity(intent);
}
}, baidustart, baiduend, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
//找到TextView控件
TextView tvColor = (TextView) findViewById(R.id.tv);
// 在点击连接时,有执行的动作,都必须设置MovementMethod对象
tvColor.setMovementMethod(LinkMovementMethod.getInstance());
// 给TextView添加图片
Drawable d = getResources().getDrawable(R.drawable.ic_launcher);
d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BASELINE);
style.setSpan(span, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);//显示在字符串开始的地方
//给TextView控件设置SpannableString对象
tvColor.setText(style);
}
}
(四)要跳转到的Activity页面的代码
package com.example.newa;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.URLUtil;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;
public class WebActivity extends Activity {
// 定义布局内的控件
WebView webView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_web);
// 实例化控件
webView = (WebView) findViewById(R.id.main_wv);
toWeb();
}
/**
* 跳转到网络页面
*/
public void toWeb() {
// 设置页面显示的URL地址
String url = getIntent().getStringExtra("url");
webView.loadUrl(url);
// 一般要设置WebViewClient,才能让网页在本页面布局内显示,否则会跳转到浏览器软件打开页面
webView.setWebViewClient(new WebViewClient() {
// shouldOverrideUrlLoading方法return true
// 表示我加载后这个Intent就消费了,不再跳转到其他页面。
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Log.e("TAG", "你点击到我了"+url);
//重定向,不设置的话,很多网址是不能链接到的
view.loadUrl(url);
return true;
}
});
// 取消滚动条
webView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
// 添加网页的文本,支持java的JavaScript显示
// webView.loadDataWithBaseURL(null, string, null, "utf-8", null);
// 获取WebView的设置对象,能设置是否支持缩放或是否在页面显示图片等等。
WebSettings settings = webView.getSettings();
// 设置是否支持缩放
settings.setSupportZoom(false);// 有时无效!
// 设置是否阻止显示图片
// settings.setBlockNetworkImage(true);
// 设置先从本地获取数据,没有的话再请求网络数据
settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
// 设置字体的大小
settings.setTextZoom(20);
// 支持javaScript
settings.setJavaScriptEnabled(true);
}
/**
* 按键响应,在WebView中查看网页时,按返回键的时候按浏览历史退回,如果不做此项处理则整个WebView返回退出
*/
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()) {
// 返回键退回
webView.goBack();
return true;// 直接返回
}
finish();// 关闭页面
return super.onKeyDown(keyCode, event);
}
/**
* 回退页面
*/
public void toback(View view) {
if (webView.canGoBack()) {
// 退回
webView.goBack();
} else {
Toast.makeText(this, "没有能回退的页面了", Toast.LENGTH_SHORT).show();
}
}
/**
* 前一个页面
*/
public void topre(View view) {
if (webView.canGoForward()) {
// 前进
webView.goForward();
} else {
Toast.makeText(this, "没有能前进的页面了", Toast.LENGTH_SHORT).show();
}
}
}
这里使用WebView显示页面确实是有点麻烦的,但是也避免也打开其他浏览器。
如果是要直接跳转网页,可以值主方法的类中进行简单修改就可以了:
//跳转到自带的浏览器中
Intent intent = new Intent();
intent.setAction("android.intent.action.VIEW");
Uri content_url = Uri.parse("http://www.cnblogs.com");
intent.setData(content_url);
intent.setClassName("com.android.browser","com.android.browser.BrowserActivity"); startActivity(intent);
//但是有时候它不给比跳转到你指定的网页,只是显示默认浏览器的主页!!
(五)程序运行前,还要在AndroidManifest中注册WebActivity,并且添加网络权限;
<uses-permission android:name="android.permission.INTERNET"/>
<activity android:name="com.example.newa.WebActivity" />
程序运行后的效果:
点击“我的博客”文本部分,显示的界面:
上面是SpannableString在TextView中的应用,其实在EditText中应用也是比较多的,比如在输入框中添加一个表情,使用 的就是图片的Span对象。