ndroid 中的 TextView 组件常用于显示文本内容,其实它也可以显示 HTML 的内容。简单来讲,这就需要先把 HTML 的内容以字符串的形式获取后,经过 android.text.Html.fromHtml()转化成 Spanned 的格式,然后将其传递到 TextView 的 setText()方法中,这样就可以在 TextView 中显示 HTML 页面的内容了。需要注意的是,并不是所有的 HTML 标签在 TextView 中都是支持的,且官方文档并没有明确的说明支持 HTML 标签列表,通过查看 Android 源代码,可以得到简单的支持列表。
{<br>,< p>,< div align=>,< strong>, <b>, <em>, <cite>, <dfn>, <i>, <big>, <small>, <font size=>, <font color=>, <blockquote>, <tt>, <a href=>, <u>, <sup>, <sub>, <h1>,<h2>,<h3>,<h4>,<h5>,<h6>, <img src=>, <strike>}
1
下面的示例来介绍如何在 TextView 中显示一段 HTML 内容,要显示的这段 HTML 内容即包含超链接内容,也包含有图片。
在 TextView 中显示 HTML 内容
显示的过程中最主要的过程就是调用 Android.text.Html 类提供的 fromHtml()方法,将一段 HTML 内容转化为 Spanned 对象。
Android.text.Html 类提供的 fromHtml()方法使用如下清单 4
fromHtml()方法定义
public static Spanned fromHtml(String source, ImageGetter imageGetter,
TagHandler tagHandler) {
……
HtmlToSpannedConverter converter =
new HtmlToSpannedConverter(source, imageGetter, tagHandler, parser);
return converter.convert();
}
1234567
source,就是包含 HTML 内容的字符串。而 Html.ImageGetter 和 Html.TagHandler 是两个接口,提供给开发者继承使用。
imageGetter, 如果要显示图片是需要被继承的,重写 getDrawable(String source)方法,用于获取 HTML 里面的图片来显示在 TextView 中。
tagHandler,其作用是把 HTML 带标记的文本内容字符串转化成可以显示效果的的 Spanned 字符串 。由于并非所有的 HTML 标签都可以转化,所以在使用时,用户需要自己添加一些必要的标签和处理方法时才会继承使用的。
在本例中使用 fromHtml()方法之前,要准备好该方法要用的三个参数内容,首先将 HTML 字符串内容准备好,在项目中需要创建两个类 MImageGetter 和 MTagHandler 分别继承于 ImageGetter 和 TagHandler,分别用户图片的获取,和特殊标签的支持。
MImageGetter
继承于 ImageGetter,重写 getDrawable (String source) 方法中从 assets 路径下取出的图片流(这里当然也可以通过网络操作来完成图片流的获取),最后获得可供显示的图片对象,例如 Drawable 对像。由于 Android 设备的异构性,为了有更好的显示效果,通常需要获取屏幕大小,然后调用 drawable.setBounds () 还可以重新设置图片的大小, 最后返回合适大小的图片 Drawable 对象。 由此 Spanned 中的 ImageSpan 就获得了图像被显示在 TextView 中对应位置了。
TypedValue typedValue = new TypedValue();
typedValue.density = TypedValue.DENSITY_DEFAULT;
drawable = Drawable.createFromResourceStream(null, typedValue, is, "src");
DisplayMetrics dm = c.getResources().getDisplayMetrics();
int dwidth = dm.widthPixels-10;//padding left + padding right
float dheight = (float)drawable.getIntrinsicHeight()*(float)dwidth/(float)drawable.getIntrinsicWidth();
int dh = (int)(dheight+0.5);
int wid = dwidth;
int hei = dh;
drawable.setBounds(0, 0, wid, hei);DisplayMetrics dm = c.getResources().getDisplayMetrics();
12345678910
MTagHandler
继承于 TagHandler,重写了 handleTag()方法,为的是支持部分标签,这四个标签是在 formHtml()方法中本身是不支持。如果开发者认为安卓 TagHandler 提供的默认标签解析已经够用,直接在 fromHtml()方法中第三个参数的地方填写 null 既可。
重写 handleTag()方法
public void handleTag(final boolean opening, final String tag, Editable output, final XMLReader xmlReader) {
if (tag.equals("ul") || tag.equals("ol") || tag.equals("dd")) {
if (opening) {
mListParents.add(tag);
} else mListParents.remove(tag);
} else if (tag.equals("li") && !opening) {
handleListTag(output);
}
}
private void handleListTag(Editable output) {
……
}
123456789101112
最后,在完成了 MImageGetter、MTagHandler 以后,就可以通过 formHtml()方法将 HTML 内容转化为可供显示的 SpannableString,将 SpannableString 通过 setText 方法放入 TextView 中,就可以显示图文并茂的内容了。
progressBar.setVisibility(View.GONE);
text.setText(Html.fromHtml(htmlCont, new MImageGetter(text,MainActivity.this), new MTagHandler()));
text.setVisibility(View.VISIBLE);
123
MImageGetter、MTagHandler 如下:
者博客
http://www.jianshu.com/u/0fa6f5d09040
文章目录
前言
场景
实现方式
drawable属性
Spannable使用
HTML显示
总结
0
前言
在使用TextView的时候,我们经常需要在TextView中进行图文混排,比如在QQ中聊天的消息中的表情,底部tab图标等。
1
场景
2
实现方式
Android官方对TextView的图文混排提供了支持,我们可以从以下三种方式实现TextView的图文混排:
1.在TextView中使用Compound Drawable属性;
2.在TextView中使用Spannable多样式显示;
3.在TextView中显示HTML文本。
3
drawable属性
在TextView中使用Compound Drawable属性可以在文字的上下左右放置drawable,效果如下:
一共有两种方式可以实现:XML布局设置和Java代码设置。
1. xml布局
2. java代码
注意:必须setBounds测量图片边界,否则不显示。
3.缺陷
当TextView设置成固定大小时,由于文字距离边界的距离过大,会导致文字与图片之间设置的间距无效,如下图。
解决方案:
①设置TextView的内填充
通过设置paddingLeft、paddingRight、paddingTop、paddingBottom来缩写这个间距
②自定义TextView重新布局
a.先自定义属性iconPadding来设置间距,并提供方法给外部调用。
b.重写setCompoundDrawablesWithIntrinsicBounds方法来获取我们设置的drawable宽高。
c.最后重写onLayout方法。
可以先参考:Android技巧之drawablePadding的那些事(https://yuxingxin.com/2015/11/05/DrawablePadding/),该篇文章只解决了左右失效的问题。后期会整理个解决图文混排的工具库,里面会有具体方案。
4
Spannable使用
1.简介
setText(CharSequence text)中接收的是CharSequence。而SpannableString和SpannableStringBuilder是其实现类,是可以直接赋值的。并且两者的setSpan方法可以设置一些格式对象(例如字体大小、下划线、替换为图片等),这就可以实现富文本了。
Spannable实现子类:SpannableString,SpannableStringBuilder(可变,类似于StringBuilder)。
Spannable中定义了抽象方法:setSpan(Object what, int start, int end, int flags)和removeSpan(Object what)。这两个方法实现了对字符串的灵活编辑。
其中setSpan方法包含如下参数:
flags常用的有四种
通常在insert方式才生效,平时不生效,具体看:Explain the meaning of Span flags like SPAN_EXCLUSIVE_EXCLUSIVE。(https://stackoverflow.com/questions/9879233/explain-the-meaning-of-span-flags-like-span-exclusive-exclusive)
2.常用span类
3.使用方式
其中ImageSpan默认对其方式有两种:ALIGN_BOTTOM及ALIGN_BASELINE。很可惜我们平常用的居中对其的方式没有,不过可以通过自定义实现,后续会在开源出来。
4.效果
5
HTML显示
一般显示HTML内容有两种方式:
使用 Android 提供的 WebView 控件。
通过将 HTML 内容转化为 Spanned 格式在 TextView 中进行显示。
现在大多数都用WebView的方式。但是并不是所有的场景下都适合使用 WebView 来显示 HTML 内容,例如,如果应用要显示的内容只是一部分 HTML 片段,就可以利用 TextView 来进行显示,并且效率较高。
由于这种方式不太常用,就不深入介绍,里面可以实现的效果还是很好的。
1.简介
Android 中的 TextView 组件常用于显示文本内容,其实它也可以显示 HTML 的内容。
简单来讲,这就需要先把 HTML 的内容以字符串的形式获取后,经过 android.text.Html.fromHtml转化成 Spanned 的格式,然后将其传递到 TextView 的 setText方法中,这样就可以在 TextView 中显示 HTML 页面的内容了。
需要注意的是,并不是所有的 HTML 标签在 TextView 中都是支持的,且官方文档并没有明确的说明支持 HTML 标签列表,通过查看 Android 源代码,可以得到简单的支持列表。
下面的示例来介绍如何在 TextView 中显示一段 HTML 内容,要显示的这段 HTML 内容即包含超链接内容,也包含有图片。
2.使用
fromHtml方法
source,就是包含 HTML 内容的字符串。Html.ImageGetter 和 Html.TagHandler 是两个接口,提供给开发者继承使用。
imageGetter, 如果要显示图片是需要被继承的,重写 getDrawable(String source)方法,用于获取 HTML 里面的图片来显示在 TextView 中。
tagHandler,其作用是把 HTML 带标记的文本内容字符串转化成可以显示效果的的 Spanned 字符串 。由于并非所有的 HTML 标签都可以转化,所以在使用时,用户需要自己添加一些必要的标签和处理方法时才会继承使用的。
继承ImageGetter
继承于 ImageGetter,重写 getDrawable (String source) 方法。通过异步操作,读取本地/网络资源,获得drawable对象。
继承TagHandler
继承于 TagHandler,重写了 handleTag方法。为了支持更多的标签,例如为了支持<ul><ol><dd>和<li>标签,这四个标签是在 formHtml方法中本身是不支持。
如果开发者认为安卓 TagHandler 提供的默认标签解析已经够用,直接在 fromHtml方法中第三个参数的地方填写 既可。
最后,通过 formHtml方法将 HTML 内容转化为可供显示的 SpannableString,将 SpannableString 通过 setText 方法放入 TextView 中,就可以显示图文并茂的内容了。
用户交互
formHtml方法已经将 HTML 内容中的超链接和图片转义成为 UrlSpan 和 ImageSpan,进而在 TextView 中完成显示。但是此时是没有任何用户交互的,用户只能看到 HTML 的内容,下面介绍如何添加用户交互功能。
要完成用户交互,这里我们需要在 TextView 中还需要调用textView.setMovementMethod方法。
Android 提供了 LinkMovementMethod 类以实现了对于文本内容中超链接的遍历,并且支持对于超链接的点击事件。
所以只要在添加下面一行代码,就可以使点击 UrlSpan 能够触发打开链接的功能。
如果想要更多的用户交互效果,可以自定义LinkMovementMethod 类,重写onTouchEvent方法来实现。
3.效果
关于HTML显示这部分,没做具体实现。具体可以看:灵活高效的在 Android Native App 开发中显示 HTML 内容(https://www.ibm.com/developerworks/cn/web/1407_zhangqian_androidhtml/index.html),里面有具体源码可以下载,HTML部分内容也是参考该篇文章完成的。
开源库:html-textview
https://github.com/PrivacyApps/html-textview
6
总结
以上就是关于图文混排的一些解决方案,相信通过这些了解,对于工作中的实际场景的使用大家会有适当的解决方案。由于实际应用较少,所以认识较为浅显,可能有些地方描述不当,后期会考虑封装个解决图文混排的工具类,加深下理解。
.实现的效果:
2.实现代码my_toast_show_view.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="bottom|center_horizontal"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="150dp"
android:background="@drawable/shape_toast_rect_corner"
android:gravity="center"
android:minWidth="100dp"
android:orientation="vertical"
android:paddingLeft="5dp"
android:paddingTop="5dp"
android:paddingRight="5dp"
android:paddingBottom="5dp">
<TextView
android:id="@+id/textItem"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:lineSpacingMultiplier="1.2"
android:maxWidth="450dp"
android:paddingLeft="10dp"
android:paddingTop="5dp"
android:paddingRight="10dp"
android:paddingBottom="8dp"
android:textColor="#fff"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
shape_toast_rect_corner.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="#9f000000"/>
<corners
android:radius="5dp" />
</shape>
ToastUtil
package com.antbyte.listdemo;
import android.content.Context;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
public class ToastUtil {
//显示弹出信息
public static void ToastMessage(String message) {
Context context = MyApp.mApp;
try {
View toastRoot = ((LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.my_toast_show_view, null);
Toast toast = new Toast(context);
toast.setView(toastRoot);
TextView tv = (TextView) toastRoot.findViewById(R.id.textItem);
tv.setText(message);
toast.setGravity(Gravity.BOTTOM, 0, 0);
toast.show();
} catch (Exception e) {
e.printStackTrace();
}
}
}
MyApp
package com.antbyte.listdemo;
import android.app.Application;
public class MyApp extends Application {
public static MyApp mApp;
@Override
public void onCreate() {
super.onCreate();
mApp = this;
}
}
3.调用方法
ToastUtil.ToastMessage("提示信息");
*请认真填写需求信息,我们会在24小时内与您取得联系。