一个简单的Android富文本TextView实现
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 24.0px Helvetica; color: #555555 }
p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 22.0px Helvetica; color: #555555 }
p.p3 { margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Helvetica; color: #555555 }
p.p4 { margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Helvetica; color: #555555; min-height: 17.0px }
p.p5 { margin: 0.0px 0.0px 0.0px 0.0px; font: 20.0px Helvetica; color: #555555 }
p.p6 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Helvetica; color: #555555 }
p.p7 { margin: 0.0px 0.0px 0.0px 0.0px; text-align: justify; font: 14.0px Helvetica; color: #555555 }
p.p8 { margin: 0.0px 0.0px 0.0px 0.0px; text-align: right; font: 13.0px "PT Mono"; color: #666666 }
p.p9 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px "PT Mono"; color: #999999 }
p.p10 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px "PT Mono"; color: #cccccc }
p.p11 { margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Helvetica; color: #555555 }
p.p12 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px "PT Mono"; color: #cccccc; min-height: 15.0px }
p.p13 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px "PT Mono"; color: #f99157 }
p.p14 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px "PT Mono"; color: #66cccc }
p.p21 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px "PT Mono"; color: #cc99cc }
li.li7 { margin: 0.0px 0.0px 0.0px 0.0px; text-align: justify; font: 14.0px Helvetica; color: #555555 }
li.li8 { margin: 0.0px 0.0px 0.0px 0.0px; text-align: right; font: 13.0px "PT Mono"; color: #666666 }
li.li9 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px "PT Mono"; color: #999999 }
li.li10 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px "PT Mono"; color: #cccccc }
li.li15 { margin: 0.0px 0.0px 0.0px 0.0px; text-align: right; font: 13.0px "PT Mono"; color: #666666 }
li.li16 { margin: 0.0px 0.0px 0.0px 0.0px; text-align: justify; font: 14.0px Helvetica; color: #cccccc }
li.li17 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px "PT Mono"; color: #99cc99 }
li.li18 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px "PT Mono"; color: #f2777a }
li.li19 { margin: 0.0px 0.0px 0.0px 0.0px; text-align: justify; font: 14.0px Helvetica; color: #cccccc }
li.li20 { margin: 0.0px 0.0px 0.0px 0.0px; text-align: justify; font: 14.0px Helvetica; color: #555555 }
li.li21 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px "PT Mono"; color: #cc99cc }
span.s1 { }
span.s2 { background-color: #2d2d2d }
span.s3 { color: #cc99cc; background-color: #2d2d2d }
span.s4 { color: #99cc99; background-color: #2d2d2d }
span.s5 { color: #f99157; background-color: #2d2d2d }
span.s6 { color: #cccccc; background-color: #2d2d2d }
span.s7 { color: #6599cc; background-color: #2d2d2d }
span.s8 { color: #66cccc; background-color: #2d2d2d }
span.s9 { color: #999999; background-color: #2d2d2d }
span.s10 { background-color: #2d2d2d }
span.s11 { background-color: #2d2d2d }
span.s12 { color: #f2777a; background-color: #2d2d2d }
span.s13 { color: #f2777a; background-color: #2d2d2d }
span.s14 { color: #cccccc; background-color: #2d2d2d }
span.s15 { background-color: #2d2d2d }
table.t1 { margin: 20.0px 0.0px 20.0px 0.0px; border-style: solid; border-width: 1.0px 1.0px 1.0px 1.0px; border-color: #dddddd #dddddd #dddddd #dddddd; border-collapse: collapse }
table.t2 { border-collapse: collapse }
td.td1 { width: 254.0px; border-style: solid; border-width: 0.0px 1.0px 3.0px 0.0px; border-color: transparent #eeeeee #dddddd transparent; padding: 8.0px 8.0px 10.0px 8.0px }
td.td2 { width: 411.0px; border-style: solid; border-width: 0.0px 1.0px 3.0px 0.0px; border-color: transparent #eeeeee #dddddd transparent; padding: 8.0px 8.0px 10.0px 8.0px }
td.td3 { width: 254.0px; background-color: #f9f9f9; border-style: solid; border-width: 0.0px 1.0px 1.0px 0.0px; border-color: transparent #eeeeee #dddddd transparent; padding: 8.0px 8.0px 8.0px 8.0px }
td.td4 { width: 411.0px; background-color: #f9f9f9; border-style: solid; border-width: 0.0px 1.0px 1.0px 0.0px; border-color: transparent #eeeeee #dddddd transparent; padding: 8.0px 8.0px 8.0px 8.0px }
td.td5 { width: 254.0px; border-style: solid; border-width: 0.0px 1.0px 1.0px 0.0px; border-color: transparent #eeeeee #dddddd transparent; padding: 8.0px 8.0px 8.0px 8.0px }
td.td6 { width: 411.0px; border-style: solid; border-width: 0.0px 1.0px 1.0px 0.0px; border-color: transparent #eeeeee #dddddd transparent; padding: 8.0px 8.0px 8.0px 8.0px }
td.td7 { width: 260.0px; border-style: solid; border-width: 0.0px 1.0px 3.0px 0.0px; border-color: transparent #eeeeee #dddddd transparent; padding: 8.0px 8.0px 10.0px 8.0px }
td.td8 { width: 405.0px; border-style: solid; border-width: 0.0px 1.0px 3.0px 0.0px; border-color: transparent #eeeeee #dddddd transparent; padding: 8.0px 8.0px 10.0px 8.0px }
td.td9 { width: 260.0px; background-color: #f9f9f9; border-style: solid; border-width: 0.0px 1.0px 1.0px 0.0px; border-color: transparent #eeeeee #dddddd transparent; padding: 8.0px 8.0px 8.0px 8.0px }
td.td10 { width: 405.0px; background-color: #f9f9f9; border-style: solid; border-width: 0.0px 1.0px 1.0px 0.0px; border-color: transparent #eeeeee #dddddd transparent; padding: 8.0px 8.0px 8.0px 8.0px }
td.td11 { width: 260.0px; border-style: solid; border-width: 0.0px 1.0px 1.0px 0.0px; border-color: transparent #eeeeee #dddddd transparent; padding: 8.0px 8.0px 8.0px 8.0px }
td.td12 { width: 405.0px; border-style: solid; border-width: 0.0px 1.0px 1.0px 0.0px; border-color: transparent #eeeeee #dddddd transparent; padding: 8.0px 8.0px 8.0px 8.0px }
td.td13 { width: 29.0px; background-color: #f9f9f9 }
td.td14 { width: 743.0px; background-color: #f9f9f9 }
td.td15 { width: 720.0px; background-color: #f9f9f9 }
td.td16 { width: 681.0px; background-color: #f9f9f9 }
td.td17 { width: 697.0px; background-color: #f9f9f9 }
td.td18 { width: 728.0px; background-color: #f9f9f9 }
td.td19 { width: 37.0px; background-color: #f9f9f9 }
td.td20 { width: 673.0px; background-color: #f9f9f9 }
td.td21 { width: 603.0px; background-color: #f9f9f9 }
td.td22 { width: 478.0px; background-color: #f9f9f9 }
td.td23 { width: 463.0px; background-color: #f9f9f9 }
td.td24 { width: 634.0px; background-color: #f9f9f9 }
td.td25 { width: 564.0px; background-color: #f9f9f9 }
ol.ol1 { list-style-type: decimal }
Android客户端富文本
现阶段问题
在Android客户端展现一个普通数据非常的方便,直接调用textview.setText()方法,但是当TextView比较复杂时(例如存在@用户,##话题,部分字符样式、网址链接等),普通的TextView就无法完成需求,需要自己封装一个富文本TextView。
Demo
Coding 冒泡示例
##
分析
1.一个TextView中不同类别的信息,需要由不同样式的显示,一般的用法textview.setTextColor(color)会将所有的文字变成同一种颜色,这显然是不符合要求的。为了实现这一个需求,我们将会用到SpannableStringBuilder这个类。
预备知识
SpannableStringBuilder:
基本概念
SpannableStringBuilder 和 StringBuilder类似,都可以存储字符串,不同的是SpannableStringBuilder有一个setSpan()函数,可以给存储的String添加不同的样式。如加下划线、背景色、字体颜色、字体大小等。
另外需要注意的是,当SpannableStringBuilder中存储了一个有样式的String,当把spannableStringBuilder展示在TextView、EditTextView中时,能显示这些样式;当展示在canvas上时,因为Canvas不支持SpannableStringBuilder的额外信息,所以会退化成一个普通的String,不显示样式信息。
setSpan()函数
void setSpan(Object what,int startIndex,int endIndex,int flag);
说明:
|
参数 |
说明 |
|
Object what |
设置Span样式 |
|
int startIndex |
样式开始的Index |
|
int endIndex |
样式结束的Index |
|
int flag |
新插入字符的样式设置 |
注意点:
- endIndex:字体样式结束的Index,该Index对应的字符不使用样式,比如有一个字符串为s = “abcd”,s.setSpan(span,0,2,flag),此时第0、1个字符ab使用了样式span,endIndex对应的字符c不使用。
- flag:取值如下
|
取值 |
说明 |
|
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE |
前后都不包括,即在指定范围的前面和后面插入新字符都不会应用新样式 |
|
Spannable.SPAN_EXCLUSIVE_INCLUSIVE |
前面不包括,后面包括。即仅在范围字符的后面插入新字符时会应用新样式 |
|
Spannable.SPAN_INCLUSIVE_EXCLUSIVE |
前面包括,后面不包括。 |
|
Spannable.SPAN_INCLUSIVE_INCLUSIVE |
前后都包括 |
简单示例
|
1 2 3 4 5 6 |
//设置字体颜色 textview1 = (TextView) findViewById(R.id.text1); SpannableStringBuilder spannableStringBuilder1 = new SpannableStringBuilder("Android"); ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(Color.BLUE); spannableStringBuilder1.setSpan(foregroundColorSpan, 0, 3, Spannable.SPAN_EXCLUSIVE_INCLUSIVE); textview1.setText(spannableStringBuilder1); |
效果:
多种Span
由以上的简单示例我们可以看出,设置一个样式的一般步骤是:
- 构造一个SpannableStringBuilder
- 构造一个Span,并设置在SpannableStringBuilder上
- 将SpannableStringBuilder绑定在TextView上展示
设置字体颜色
这个已经在简单示例中展示
设置字体背景颜色
|
1 2 3 4 5 6 |
//设置字体背景颜色 textview2 = (TextView) findViewById(R.id.text2); SpannableStringBuilder spannableStringBuilder2 = new SpannableStringBuilder("Android"); BackgroundColorSpan backgroundColorSpan = new BackgroundColorSpan(Color.RED); spannableStringBuilder2.setSpan(backgroundColorSpan, 0, 3, Spannable.SPAN_EXCLUSIVE_INCLUSIVE); textview2.setText(spannableStringBuilder2); |
效果:
设置字体大小
|
1 2 3 4 5 6 |
//设置字体大小 textview3 = (TextView) findViewById(R.id.text3); SpannableStringBuilder spannableStringBuilder3 = new SpannableStringBuilder("Android"); AbsoluteSizeSpan absoluteSizeSpan = new AbsoluteSizeSpan(30); spannableStringBuilder3.setSpan(absoluteSizeSpan, 0, 3, Spannable.SPAN_EXCLUSIVE_INCLUSIVE); textview3.setText(spannableStringBuilder3); |
效果:
设置字体
|
1 2 3 4 5 6 |
//设置字体(加粗斜体) textview4 = (TextView) findViewById(R.id.text4); SpannableStringBuilder spannableStringBuilder4 = new SpannableStringBuilder("Android"); StyleSpan styleSpan = new StyleSpan(Typeface.BOLD_ITALIC); spannableStringBuilder4.setSpan(styleSpan, 0, 3, Spannable.SPAN_EXCLUSIVE_INCLUSIVE); textview4.setText(spannableStringBuilder4); |
效果:
设置下划线
|
1 2 3 4 5 6 |
//设置下划线 textview5 = (TextView) findViewById(R.id.text5); SpannableStringBuilder spannableStringBuilder5 = new SpannableStringBuilder("Android"); UnderlineSpan underlineSpan = new UnderlineSpan(); spannableStringBuilder5.setSpan(underlineSpan, 0, 3, Spannable.SPAN_EXCLUSIVE_INCLUSIVE); textview5.setText(spannableStringBuilder5); |
效果:
设置下划线
|
1 2 3 4 5 6 |
//设置删除线 textview6 = (TextView) findViewById(R.id.text6); SpannableStringBuilder spannableStringBuilder6 = new SpannableStringBuilder("Android"); StrikethroughSpan strikethroughSpan = new StrikethroughSpan(); spannableStringBuilder6.setSpan(strikethroughSpan, 0, 3, Spannable.SPAN_EXCLUSIVE_INCLUSIVE); textview6.setText(spannableStringBuilder6); |
效果:
设置多种样式
除了设置一个样式以外,SpannableStringBuilder还支持设置多个样式。
|
1 2 3 4 5 6 7 8 9 |
//设置多种样式 textview7 = (TextView) findViewById(R.id.text7); SpannableStringBuilder spannableStringBuilder7 = new SpannableStringBuilder("Android"); spannableStringBuilder7.setSpan(foregroundColorSpan, 0, 3, Spannable.SPAN_EXCLUSIVE_INCLUSIVE); spannableStringBuilder7.setSpan(backgroundColorSpan, 0, 3, Spannable.SPAN_EXCLUSIVE_INCLUSIVE); spannableStringBuilder7.setSpan(underlineSpan, 0, 3, Spannable.SPAN_EXCLUSIVE_INCLUSIVE); spannableStringBuilder7.setSpan(absoluteSizeSpan, 3, 6, Spannable.SPAN_EXCLUSIVE_INCLUSIVE); spannableStringBuilder7.setSpan(strikethroughSpan, 3, 6, Spannable.SPAN_EXCLUSIVE_INCLUSIVE); textview7.setText(spannableStringBuilder7); |
效果:
点击事件
实例代码
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder("Android"); spannableStringBuilder.setSpan( new ClickableSpan() { @Override public void onClick(View widget) { //do something } @Override public void updateDrawState(TextPaint ds) { //设置一些样式 //ds.setUnderlineText(false); //ds.setColor(color); } }, startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE ); |
简单实现
- 以Listview为例,我们需要实现的是每一个Item和Adapter中的getView()函数。
- 布局文件
|
|
ImageView表示该Item的发布人,和富文本没有关系,在Demo中直接写死数据。
主要内容在TextView中
- 因为每一个TextView中可能有多个不同样式的文本(#话题#,@其他用户,文本内容等),所以先封装一个文本类:
|
|
这个类封装的是一个Item中的某一个文本样式,所以我们还需要封装一个Item中的文本类:
|
1 2 3 4 5 6 |
public class Content { private List<TextObject> mList; private SpannableStringBuilder mSpannableStringBuilder; } |
这个类中有一个List成员变量,存放着该Item中所有的样式文本。
对于成员变量SpannableStringBuilder,有一个init函数,用于根据List中的TextObject拼接StringBuilder
|
1 2 3 4 5 6 7 8 9 |
//拼接SpannableStringBuilder public void initStringBuilder(){ SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(); for (int i = 0;i<mList.size();i++){ spannableStringBuilder.append(mList.get(i).getContent()); } setmSpannableStringBuilder(spannableStringBuilder); } |
到现在,数据准备工作已经全部完成,现在就要显示这些数据了。
- getView()函数
getview函数中就可以通过content.getSpannableStringBuilder()函数获取到正文内容,然后即可根据上面的预备知识对其进行设置不同的样式和点击事件。
设置完成后,需要调用
|
1 |
viewHolder.textview.setMovementMethod(LinkMovementMethod.getInstance()); |
使其响应点击事件。
Demo效果:
Demo地址
一个简单的Android富文本TextView实现的更多相关文章
- Android - 富文本编辑器
Android富文本编辑器(一):基础知识 目前主流的基于Android富文本开发方式思路如下: 基于TextView图文混排 使用方式: TextView textView = new TextVi ...
- 一个简单的Android小实例
原文:一个简单的Android小实例 一.配置环境 1.下载intellij idea15 2.安装Android SDK,通过Android SDK管理器安装或卸载Android平台 3.安装J ...
- Android 富文本框实现 RichEditText
Android系统自带控件没有富文本框控件,如果想写一封带格式的邮件基本上不可能,EdtiText只有默认一种格式,显示不能滿足要求,!!正好项目需要研究了一下,开发了此控件,现将一些源代码开放一下, ...
- Android高效的应用程序开发工具集1---ant构建一个简单的Android工程
在java编译那些事通过提到ant编译Java工程,如今扩大到用它来构建Android目,事实上道理是相通的.变化的仅仅是使用的形式.ant构建相比IDE的优点是多个子项目使用自己定义jar包时,an ...
- springmvc 后台实体类接受前端json字符串时,其中一个属性content 接受富文本内容时 标签<p>、<span> 这些标签丢失问题解决
问题描述: 前端一个字段 <script id="editor" type="text/plain" name="content" s ...
- Android 富文本编辑器实现方案
本人实现富文本编辑器的时候,总结了如下两种方案: 1. 纯 EditText 实现方案 2. 使用ScrollView作为最外层的父容器来控制展示效果 示例demo地址为:https://github ...
- 使用工具Android Studio实现一个简单的Android版的新闻APP
目的: 这是我学完Android课程后所写的一个小的.简单版的新闻APP 技术概要: 用到了SQLite数据库,用它来存储每篇新闻下的评论 新闻的来源是新浪新闻,我通过使用Fiddler来对新浪新闻A ...
- 一个简单的Dump转文本工具—Dump2Text
每次电脑重装都得烦心,要把庞大的IDE重新配置一次,正准备安装Visual Stdio 2010,上网找镜像的时候发现,Visual Stdio 2013推出了Community版,不仅没有lite掉 ...
- 实现一个简单的android开关
近期在学习android中的graphics中绘图系列.依照大神思路.找葫芦画瓢实现了一个开关.如图下: 记录一下实现方式: 1.画背景 上图形状.分成两个半圆与一个矩形,那么代码能够写成: priv ...
随机推荐
- JavaScript滚动条插件源码
这是过年的时候自己写的js滚动条插件的源码,做出的效果自己并不满意,正因为做的并不满意所以回头重新巩固和深入学习js,这个插件有如下几个不太满意的地方: 内容的过度效果,可以参阅QQ客户端最近会话列表 ...
- JSON 转javabean 利器
别再对着json来手写javabean啦.这个工作完全不要脑子,而且耗时. 这里给大家提供三种方式: android studio版: 万能的插件:GsonFormat 如何安装? Preferenc ...
- 是否要学SpringMVC
如题,希望大侠们指出,不能用Spring就觉得他什么都好,本帖子意在实际工作中,对是否将Spring引入项目及如何更好的使用Spring提出启发式意见.目前已有高人表达了自己对Spring的不满,让我 ...
- iOS关于启动页自定义特殊处理
平常开发中对于启动页可能会有一些特别的要求,比如在启动页加动画或加一些按键可以响应事件等,最近项目中要在启动页增加版本号,因为版本号是不断的改变,所以要动态实现把它加到启动页上:在XCode上面配置的 ...
- runtime之玩转成员变量
前言: 不铺垫那么多,单刀直入吧:runtime是一个C和汇编写的动态库,就像是一个小小的系统,将OC和C紧密关联在一次,这个系统主要做两件事情. 1,封装C语言的结构体和函数,让开发者在运行时创建, ...
- Mysql查询按照某字段指定顺序排序
在项目当中用到Sphinx的时候,很多人遇到了这样的问题:使用mysql+Sphinx检索出了相关度的ID后,如何按照指定ID在Mysql中进行排序呢?这里是我在项目中的解决方法: 1 SELECT ...
- 详解 Spotlight on Unix 监控Linux服务器
1.安装 Spotlight on Unix 下载地址:http://yunpan.cn/QNWyEEvNS4xc9 访问密码 1c7d 傻瓜安装 2.配置spotlight登陆用户,注意spotl ...
- centos7 ssh 设置key认证
vi /etc/ssh/sshd_config 查找RSAAuthentication.StrictModes.PubkeyAuthentication.AuthorizedKeysFile把所在行修 ...
- visual studio生成后调试启动又提示部分项目需要生成问题总结
长久以来若干个项目都遇到过类似的情形,已经成功生成的项目启动调试或者再生成依然认为部分项目需要生成而不是跳过.总结以往的经验,记录下来,以便大家遇到时处理. 若有多个项目提示需要重新生成,优先检查被依 ...
- JavaScript Patterns 5.3 Private Properties and Methods
All object members are public in JavaScript. var myobj = { myprop : 1, getProp : function() { return ...