首先看一幅图,是简书App的一篇文章的截图,如下:

图1,图2

上面两个图片都是文本的显示,但是由于有多种格式,所以较为复杂,例如其中有普通文本,还有加粗的文本,还有图文混排的显示等等。

一、解析HTML标签:

  Android的SDK提供了可以解析HTML标签进行特殊显示的方式。就是使用android.text包下的Html类来解析文本。该类可以对常用的HTML标签进行解析,然后给TextView控件进行显示。有两类标签比较特殊:

  1、链接类标签即a标签。使用该标签需要注意:

    !!!注意①需要开启网络权限②在href属性指定链接时必须添加http://,否则不能正确解析。③需要调用TextView控件的setMovementMethod方法传入点击后的行为,对连接通常使用系统自带的LinkMovementMethod即可,可以通过该类的getInstance()获取一个单例使用。

  2、图片类即img标签。使用该标签需要注意:

    注意:①需要使用fromHtml()有三个参数的重载,主要是第二个参数Html.ImageGetter的实例来进行图片的加载。

  下面是简单的演示代码,可以在TextView中展示普通文本,粗体文本<b>,链接<a>,图片<img>等:

    private void beforeInit(final TextView tv) {
String text="哈哈,这是一个<b>富文本显示</b>的示例,例如显示网址<a href='http://www.baidu.com'>百度</a>。还可以显示一幅图片<img src='loading'>";
tv.setMovementMethod(LinkMovementMethod.getInstance());
tv.setText(Html.fromHtml(text, new Html.ImageGetter() {
@Override
public Drawable getDrawable(String source) {
Drawable drawable = null;
try {
Field field = R.drawable.class.getField(source);
int resourceId = Integer.parseInt(field.get(null).toString());
drawable = getResources().getDrawable(resourceId);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
}catch (Exception e) {
e.printStackTrace();
}
return drawable;
}
}, null));
}

富文本示例

二、原理解析:

  其实,在TextView显示文本时,是将该段文本当做Spanned区块来看待的,例如链接可以就是URL区块,图片就是image区块等。通过Html.fromHtml()可以对文本进行解析,然后读取不同的区块并为其进行不同的操作。我们可以看一下该方法的返回值

     public static Spanned fromHtml(String source, ImageGetter imageGetter,
TagHandler tagHandler) {

  这里也可以对上面的一些问题进行说明:

  1、为什么指定链接时需要加上http://?因为在使用了LinkMovementMethod的默认行为之后,其动作就是发送一个Intent,data就是该链接的href属性。所以需要通过http://来匹配可以处理该data的Activity,如果没有的话找不到Activity则会报错crash掉程序。

  2、为什么图片的显示需要特殊的处理(即使用Html.ImageGetter)?因为图片文本解析出来只是普通的文本,真正显示图片需要从本地或者网络进行加载,通过实现该类的方法,指定图片加载的方式才能正确显示图片。

三、使用SpannableString&SpannableStringBuilder来显示文本

  上面是对一段HTML文本的解析显示,已经可以满足一些要求了,但是如果不是HTML特定标签也需要特殊的显示格式该如何处理呢?例如图2中的显示特殊颜色的可点击进入特定用户的信息界面的效果的实现。这时就可以使用标题中介绍的两种方式了,这里以SpannableString为例:

  1、二中说到,TextView显示的是一个个区块,而该类就是将文本的一部分设置成特殊的区块,所有可实现的区块类型都对应android.text.style中的一个类。如下:

    • BackgroundColorSpan 背景色
    • ClickableSpan 文本可点击,有点击事件
    • ForegroundColorSpan 文本颜色(前景色)
    • MaskFilterSpan 修饰效果,如模糊(BlurMaskFilter)、浮雕(EmbossMaskFilter)
    • MetricAffectingSpan 父类,一般不用
    • RasterizerSpan 光栅效果
    • StrikethroughSpan 删除线(中划线)
    • SuggestionSpan 相当于占位符
    • UnderlineSpan 下划线
    • AbsoluteSizeSpan 绝对大小(文本字体)
    • DynamicDrawableSpan 设置图片,基于文本基线或底部对齐。
    • ImageSpan 图片
    • RelativeSizeSpan 相对大小(文本字体)
    • ReplacementSpan 父类,一般不用
    • ScaleXSpan 基于x轴缩放
    • StyleSpan 字体样式:粗体、斜体等
    • SubscriptSpan 下标(数学公式会用到)
    • SuperscriptSpan 上标(数学公式会用到)
    • TextAppearanceSpan 文本外貌(包括字体、大小、样式和颜色)
    • TypefaceSpan 文本字体
    • URLSpan 文本超链接
 public class MainActivity extends AppCompatActivity {

     @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView t1 = (TextView) findViewById(R.id.txtOne);
TextView t2 = (TextView) findViewById(R.id.txtTwo); SpannableString span = new SpannableString("红色打电话斜体删除线绿色下划线图片:.");
//1.设置背景色,setSpan时需要指定的flag,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE(前后都不包括)
span.setSpan(new ForegroundColorSpan(Color.RED), 0, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
//2.用超链接标记文本
span.setSpan(new URLSpan("tel:4155551212"), 2, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
//3.用样式标记文本(斜体)
span.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), 5, 7, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
//4.用删除线标记文本
span.setSpan(new StrikethroughSpan(), 7, 10, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
//5.用下划线标记文本
span.setSpan(new UnderlineSpan(), 10, 16, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
//6.用颜色标记
span.setSpan(new ForegroundColorSpan(Color.GREEN), 10, 13,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
//7.//获取Drawable资源
Drawable d = getResources().getDrawable(R.drawable.icon);
d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
//8.创建ImageSpan,然后用ImageSpan来替换文本
ImageSpan imgspan = new ImageSpan(d, ImageSpan.ALIGN_BASELINE);
span.setSpan(imgspan, 18, 19, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
t1.setText(span);
}
}

SpannableString的简单使用

效果图如下:

  最后在说一下,对于开始提出的效果的两种实现:

  1、使用URLSpan,其参数就是Intent中data的值,相当于和上面的链接一样的效果,本质上是使用隐式Intent。

  2、使用ClickableSpan:实现时需要完成几个回调方法,用于在点击时进行回调。

参考:http://www.runoob.com/w3cnote/android-tutorial-textview.html

还有一些开源的富文本显示的框架,这里介绍一个项目:https://github.com/zzhoujay/RichText

android文本排布的更多相关文章

  1. 实现LinearLayout(垂直布局,Gravity内容排布)

    首先上Gravity的代码,Android原版的Gravity搞得挺复杂的,太高端了.但基本思路是使用位运算来做常量,我就自己消化了一些,按自己的思路来实现. 先上代码,在做分析. package k ...

  2. GridView 二维排布

    与ListView一维排布相对 public class MainActivity extends Activity implements AdapterView.OnItemClickListene ...

  3. CSS布局之div交叉排布与底部对齐--flex实现

    最近在用wordpress写页面时,设计师给出了一种网页排布图样,之前从未遇到过,其在电脑上(分辨率大于768px)的效果图如下: 而在手机(分辨率小于等于768px)上要求这样排列: 我想到了两种方 ...

  4. 按照excel文档中的内容在当前cad图纸中自动排布实体

    本例实现的主要功能是读取excel文档中的内容,其次是将按照读取的信息在当前cad图纸中添加相应的实体.下面先介绍实现代码: CString excelPath; //外部excel文档的地址 Upd ...

  5. Python中cv2库和matplotlib库色彩空间排布不一致

    今天在python中读如图片时发现以下问题: 1.在from matplotlib import pyplot as plt之后,再import cv2 cv2.imshow()不能正常使用,还不知道 ...

  6. css 行内水平均等排布方式

    <div class="justify"> <span>测试1</span> <span>测试2</span> < ...

  7. React实现座位排布组件

    React实现座位排布组件 最近在开发一个影院系统的后台管理系统,该后台可以设置一个影厅的布局. 后台使用的是react框架,一位大神学长在几天之内就把这个控件研究出来了,并进行了较为严密的封装,佩服 ...

  8. Android文本输入框(EditText)切换密码的显示与隐藏

    package cc.c; import android.app.Activity; import android.os.Bundle; import android.text.Selection; ...

  9. Gulan查询UI排布

    遇到一个问题,如何在相对布局里把两个item放在同一行,而且高度一样呢? <RelativeLayout xmlns:android="http://schemas.android.c ...

随机推荐

  1. vue项目打包后想发布在apache www/vue 目录下

    使用的是vue-element-admin做示例,可以参考Vue项目根据不同运行环境打包项目,其他项目应该大同小异. 使用vue-router的browserHistory模式,配置mode: 'hi ...

  2. gRPC全局异常捕获

    gRPC全局异常捕获 引 一般的.net项目比如ASP.NET.控制台程序.Windows服务.桌面程序等都会有framework自带的全局异常捕获机制.ASP.NET的ExceptionFilter ...

  3. 【codeforces 255D】Mr. Bender and Square

    [题目链接]:http://codeforces.com/problemset/problem/255/D [题意] 给你一个n*n的方框; 给你一个方块;(以下说的方块都是单位方块) 每一秒钟,可以 ...

  4. Java基础学习总结(7)——Object类

    一.Object类介绍 Object类在JAVA里面是一个比较特殊的类,JAVA只支持单继承,子类只能从一个父类来继承,如果父类又是从另外一个父类继承过来,那他也只能有一个父类,父类再有父类,那也只能 ...

  5. js 判断是否滚动到底部

    $(window).scroll(function(){ var scrollTop = $(this).scrollTop(); //scrollTop() 方法返回或设置匹配元素的滚动条的垂直位置 ...

  6. thinkphp5项目--个人博客(二)

    thinkphp5项目--个人博客(二) 项目地址 fry404006308/personalBlog: personalBloghttps://github.com/fry404006308/per ...

  7. 福建省赛--Problem E The Longest Straight(标记+二分)

    Problem E The Longest Straight Accept: 71    Submit: 293 Time Limit: 1000 mSec    Memory Limit : 327 ...

  8. zzulioj--1831-- 周末出游(vector建图+dfs)

    1831: 周末出游 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 22  Solved: 8 SubmitStatusWeb Board Descr ...

  9. nyoj--12--喷水装置(二)(区间覆盖问题+贪心)

    喷水装置(二) 时间限制:3000 ms  |  内存限制:65535 KB 难度:4 描述 有一块草坪,横向长w,纵向长为h,在它的橫向中心线上不同位置处装有n(n<=10000)个点状的喷水 ...

  10. 如何启动和关闭MySQL?(四)

    分为: 图形化 命令行 方法一:在“计算机”的图标上右键,然后选择“管理”,双击“服务和应用程序”,然后选择“服务”,找到“MySQL”这个服务,然后点击“右键”,就可以进行“停止”和“重新启动”的操 ...