Android-TextView设置多种颜色及部分点击事件
前言
最近项目中有一个小小的细节,就是一般温馨提示语,一段文字,但是中间会包含一些字体可点击,有特殊颜色,比如下图的温馨提示:
一般实现方式有以下几种:
1. 拼接
2.加载 Html
3.使用
其中的第一种方法,这里就不考虑了,因为这里也不确定字体到底占几行,并且链接文字位置也不可控
那下面就来看一下后面两种的实现方式。
用Html实现
这里主要就是用 html 语句。然后设置 即可。如:
String html = "<html><font color=\"#666666\">如您的账号暂未绑定手机,或有其他疑问,请" +"font><font color=\"#0000ff\">联系客服font>html>";tv_html.setText(Html.fromHtml(html));
这里我们可以看到,如果你的 sdk 的版本 》= 24 的时候,这个 ( ) 方法是显示已经废弃了的,点进去看一下情况:
很显然,我们应该使用下面的两个参数的方法,但是第二个参数 flag 是什么意思呢?
翻一下官方文档,粗略的解释一下这几个常量的含义:
Flags含义
CT
html 块元素之间使用一个换行符分隔(换行)
Y
html 块元素之间使用两个换行符分隔(空一行)
应该使用CSS颜色值,而不是颜色中定义的颜色
E
默认情况下,< >元素内的文本与其他文本使用一个换行符分隔
默认情况下,< div >元素中的文本将与其他文本使用一个换行字符分隔
默认情况下,< h1>~< h6>元素中的文本将与其他文本使用一个换行字符分隔
默认情况下,< ul>元素中的文本将与其他文本使用一个换行字符分隔
默认情况下,< li>元素中的文本将与其他文本使用一个换行字符分隔
默认情况下,< p>元素中的文本将与其他文本使用一个换行字符分隔
在< p >元素内,用“\ n”将连续的文本行分隔 (换行?)
在< p >或< li >元素中,用“\ n”将每一行文本分隔 (换行?)
具体的效果,中有人给出了一个效果对比:点击查看详情
一般情况下,我们块元素之间空一行就可以了,即采用 Y 这个 flag。
然后适配一下版本,最终的代码为:
@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);tv_html = (TextView) findViewById(R.id.tv_html);String html = "如您的账号暂未绑定手机,或有其他疑问,请" +"联系客服";tv_html.setText(fromHtml(html));}@SuppressWarnings("deprecation")public Spanned fromHtml(String source) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {return Html.fromHtml(source, Html.FROM_HTML_MODE_LEGACY);} else {return Html.fromHtml(source);}}
效果图太占空间了,这里就不贴了。
使用这种方式有个问题,就是文字效果出来了,怎么去处理链接,我们知道,一般的网页链接等直接使用 < ref > 标签即可,但是现在我们要点击链接实现拨打电话或者是其他行为,比如弹窗、跳转到另一个页面,这个时候好像 < ref> 就无能无力了(我没找到,有实现方法的同学欢迎留言)。所以,这里我们就用到了另外的一个方法:
使用
可以用来显示复合文本,我们可以通过 给文本设置各种各样的样式
比如上面的效果在不涉及点击效果,只显示不同字体颜色时,我们可以这么写:
public void setSpannableText() {tv_spannable = (TextView) findViewById(R.id.tv_spannable);String tips = "温馨提示:如果您的账号暂未绑定手机,或已忘记账号等疑问,\n 请联系客服10086";SpannableString spannableString=new SpannableString(tips);spannableString.setSpan(new ForegroundColorSpan(Color.BLUE),tips.length()-5,tips.length(),Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);tv_spannable.setText(tips);}
首先实例化 对象,传参就是要显示的文本,然后通过 方法设置文本风格,最后设置 。
其中 ( what, int start, int end, int flags) 方法有四个参数,下面来大致说一下各个参数的含义。
第一个 类型的参数:设置样式,如前景色、背景色、下划线、删除线等。一般样式 new 一个下面的类就好了:
含义
设置文本背景颜色
设置文本颜色
设置点击事件
设置删除线效果
设置下划线效果
设置图片
设置基于x轴的缩放
设置字体样式(粗体、斜体等)
设置下标
设置超链接
第二个参数和第三个参数:我们要特殊设置的文字的位置(该段文字的 和 )
第四个 int 类型的参数:设置一下规则(不知道是不是这样理解的),主要有以下的几种取值:
含义
SIVE
在文本前面或后面插入新的文本时,都不会应用该样式(前面不包括,后面不包括)
SIVE
在文本前插入新的文本不会应用该样式,而在文本后插入新文本会应用该样式(前面不包括,后面包括)
SIVE
在文本前插入新的文本会应用该样式,而在文本后插入新文本不会应用该样式(前面包括,后面不包括)
SIVE
在文本前面或后面插入新的文本时,都会应用该样式(前面包括,后面包括)
其实这四个参数的含义挺好记的,:排除的,即不包含 ,:包含的。
上面的例子因为设置颜色的文字是固定的,所以那种方式我认为都可以,这个根据需求来。
看到这,其实实现功能与用Html实现没什么区别,那它是如何实现可点击的效果的呢?
答案就是 方法第一个参数使用表格中的 对象,代码如下:
public void setSpannableText() {tv_spannable = (TextView) findViewById(R.id.tv_spannable);String tips = "温馨提示:如果您的账号暂未绑定手机,或已忘记账号等疑问,\n 请联系客服10086";SpannableString spannableString=new SpannableString(tips);spannableString.setSpan(new ClickableSpan() {@Overridepublic void onClick(View view) {Toast.makeText(MainActivity.this, "onClick:10086", Toast.LENGTH_SHORT).show();}}, tips.length() - 5, tips.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);tv_spannable.setText(tips);tv_spannable.setMovementMethod(LinkMovementMethod.getInstance());//设置可点击状态}
先看一下效果:
好像实现了我们想要的效果,但是字体颜色红色的呀,想要蓝色怎么办?可不可以不要下划线啊?
当然可以,重载 () 这个方法。在这个方法里设置可点击字体的颜色,以及去除下划线的处理
所以最终的代码是这个样子的:
public void setSpannableText() {tv_spannable = (TextView) findViewById(R.id.tv_spannable);String tips = "温馨提示:如果您的账号暂未绑定手机,或已忘记账号等疑问,\n 请联系客服10086";SpannableString spannableString=new SpannableString(tips);spannableString.setSpan(new ClickableSpan() {@Overridepublic void onClick(View view) {Toast.makeText(MainActivity.this, "onClick:10086", Toast.LENGTH_SHORT).show();}@Overridepublic void updateDrawState(TextPaint ds) {super.updateDrawState(ds);ds.setColor(Color.BLUE);ds.setUnderlineText(false);}},tips.length() - 6, tips.length()-1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);tv_spannable.setMovementMethod(LinkMovementMethod.getInstance());//设置可点击状态tv_spannable.setHighlightColor(Color.TRANSPARENT); //设置点击后的颜色为透明tv_spannable.setText(spannableString);}
不知道有没有人注意到,我第二个参数和第三个参数的值改变了,主要是因为我要点击的部分正好是在文本的结尾,如果按照原来的计算,那么我点击 10086 后面的空白部分也是会响应点击事件的,因为 的布局宽度并不是到 10086 就截止了,所以这里得做一下处理。
到此,已经了解了实现这种效果的两种方法。
他们各有优缺点,Html 实现起来简单,但是点击效果不好实现, 可以实现点击效果,但是得计算点击文字位置。
最后,再说一下,如何调 行间距:在 xml 中加入 :=”10dp” 这句话,里面的值自行设置。
当然,为了方便使用,我们可以做一下封装。
参考文章
使用详解
一个 设置多种颜色的 2 种高效方法
浅谈 , 实现 文本某一部分文字的点击响应