Android中Textview显示Html,图文混排,支持图片点击放大
本文首发于网易云社区
对于呈现Html文本来说,Android提供的Webview控件可以得到很好的效果,但使用Webview控件的弊端是效率相对比较低,对于呈现简单的html文本的话,杀鸡不必使用牛刀。另外如果是在Listview中使用的Webview的话,效率则更是低下。
然而,Android还提供了android.text.Html类来支持Html的解析,利用这个类,我们可以通过Textview来呈现Html文件。不过Html类并不是只是所有的标签。Html的描述如下:
This class processes HTML strings into displayable styledtext.
Not all HTML tags are supported.
一、解析Html标签
对于纯文字的Html文本来说,使用Textview来呈现很方便,一行代码就可以轻松搞定了,具体如下:
contentTextView.setText(Html.formHtml(htmlString));
二、处理img图片标签,实现图文混排
一般来说,html文件常常是含有图片,如果需要在Textview中实现文字和图片的混排,需要使用ImageGetter。ImageGetter是Html类中一个接口,作用是给img标签获取图片内容,主要提供了一个getDrawable的方法。
/**
* Retrieves images for HTML <img> tags.
*/
public static interface ImageGetter {
/**
* This methos is called when the HTML parser encounters an
* <img> tag. The <code>source</code> argument is the
* string from the "src" attribute; the return value should be
* a Drawable representation of the image or <code>null</code>
* for a generic replacement image. Make sure you call
* setBounds() on your Drawable if it doesn't already have
* its bounds set.
*/
public Drawable getDrawable(String source);
}
解析来需要实现一个ImageGetter,具体如下:
public class MyImageGetter implements ImageGetter {  
      
    WeakReference<TextView> mTextViewReference;  
    Context mContext;  
  
    public MyImageGetter(Context context, TextView textView, int with) {  
        mContext = context.getApplicationContext();  
        mTextViewReference = new WeakReference<TextView>(textView);  
    }  
  
    @Override  
    public Drawable getDrawable(String url) {  
  
        URLDrawable urlDrawable = new URLDrawable(mContext);  
          
        // 异步获取图片,并刷新显示内容  
        new ImageGetterAsyncTask(url, urlDrawable).execute();  
  
        return urlDrawable;  
    }  
      
    public class ImageGetterAsyncTask extends AsyncTask<String, Void, Drawable> {  
          
        WeakReference<URLDrawable> mURLDrawableReference;  
        String mUrl;  
  
        public ImageGetterAsyncTask(String url, URLDrawable drawable) {  
            mURLDrawableReference = new WeakReference<URLDrawable>(drawable);  
            mUrl = url;  
        }  
  
        @Override  
        protected Drawable doInBackground(String... params) {  
  
            // 下载图片,并且使用缓存  
            Bitmap bitmap = DownlaodUtils.getNetworkImageWithCache(mContext, mUrl);       
            BitmapDrawable bitmapDrawable = new BitmapDrawable(mContext.getResources(), bitmap);  
              
            Rect bounds = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());  
              
            if (mURLDrawableReference.get() != null) {  
                mURLDrawableReference.get().setBounds(bounds);  
            }  
            bitmapDrawable.setBounds(bounds);  
            return bitmapDrawable;  
        }  
  
        @Override  
        protected void onPostExecute(Drawable result) {  
            if (null != result) {  
                if (mURLDrawableReference.get() != null) {  
                    mURLDrawableReference.get().drawable = result;  
                }  
                if (mTextViewReference.get() != null) {  
                    // 加载完一张图片之后刷新显示内容  
                    mTextViewReference.get().setText(mTextViewReference.get().getText());  
                }  
            }  
        }  
    }  
      
      
    public class URLDrawable extends BitmapDrawable {  
        protected Drawable drawable;  
  
        public URLDrawable(Context context) {  
            // 设置默认大小和默认图片  
            Rect bounds = new Rect(0, 0, 100, 100);  
            setBounds(bounds);  
            drawable = context.getResources().getDrawable(R.drawable.default_image);  
            drawable.setBounds(bounds);  
        }  
  
        @Override  
        public void draw(Canvas canvas) {  
            if (drawable != null) {  
                drawable.draw(canvas);  
            }  
        }  
    }  
}  
实现了MyImageGetter之后,则需要实现图文混排就轻而易举了
MyImageGetter imageGetter = new MyImageGetter(this, contentTextView);
contentTextView.setText(Html.formHtml(htmlString, imageGetter, null));
三、图片的点击放大
前面已经实现了Textview呈现html文本,并且能够图文混排。但很多情况下,需要支持点击图片后将图片放大显示。这样,我们需要支持img标签的点击处理,能够监听到点击事件就可以实现这个功能了。这里我们可以通过实现TagHandler接口来实现这个功能。首先看下android.text.Html类中的Taghandler接口:
/**
* Is notified when HTML tags are encountered that the parser does
* not know how to interpret.
*/
public static interface TagHandler {
/**
* This method will be called whenn the HTML parser encounters
* a tag that it does not know how to interpret.
*/
public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader);
}
我们只需实现TagHandler的handleTag方法来处理img标签则可,主要是给内容设置一个ClickableSpan,具体如下:
public class MyTagHandler implements TagHandler {  
  
    private mContext;  
      
    public MyTagHandler(Context context) {  
        mContext = context.getApplicationContext();  
    }  
      
    @Override  
    public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) {  
  
        // 处理标签<img>  
        if (tag.toLowerCase(Locale.getDefault()).equals("img")) {  
            // 获取长度  
            int len = output.length();  
            // 获取图片地址  
            ImageSpan[] images = output.getSpans(len-1, len, ImageSpan.class);  
            String imgURL = images[0].getSource();  
              
            // 使图片可点击并监听点击事件  
            output.setSpan(new ClickableImage(mContext, imgURL), len-1, len, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  
        }  
    }  
      
    private class ClickableImage extends ClickableSpan {  
  
        private String url;  
        private Context context;  
          
        public ClickableImage(Context context, String url) {  
            this.context = context;  
            this.url = url;  
        }  
          
        @Override  
        public void onClick(View widget) {  
            // 进行图片点击之后的处理  
        }  
    }  
}  
实现了TagHandler之后,在formHtml传入实例则可:
MyImageGetter imageGetter = new MyImageGetter(this, contentTextView);
MyTagHandler tagHandler = new MyTagHandler(this);
contentTextView.setText(Html.formHtml(htmlString, imageGetter, tagHandler));
contentTextView.setMovementMethod(LinkMovementMethod.getInstance());
网易云产品免费体验馆,无套路试用,零成本体验云计算价值。
本文来自网易云社区,经作者戚明峰授权发布
相关文章:
【推荐】 Windows扩展屏开发总结
Android中Textview显示Html,图文混排,支持图片点击放大的更多相关文章
- TextView + Spanned实现图文混排以及图片点击交互
		
最近要实现图文混排的需求,webview过大,所以想到了用SpannableStringBuilder来实现. 不过参考了大量国内文章,大多数是教你如何实现图文混排,并没有提及图片点击交互的.有翻阅了 ...
 - DIV+CSS 图文混排的图片居中办法
		
不少人为了让 Div 图文混排的图片可以居中,给 IMG 套各式各样的 SPAN.DIV.LI 等等,以便于使用 text-align来进行居中. <div>图文混排 <br> ...
 - Unity插件之NGUI学习(5)—— 创建Label图文混排及文字点击
		
创建一个新的Scene,并按 Unity插件之NGUI学习(2)创建UI Root. 准备工作,制作Font.如今Project窗体创建一个Font目录.然后从系统自带字体目录中选择自己须要的字体,我 ...
 - iOS  图文混排 链接  可点击
		
对于这个话题 我想到 1 第一个解决方法就是使用 webView 比较经典 把所有复杂工作都交给控件本身去处理了, 但是好像好多需要自定义的地方 没法从 webView获得响应回调 :(估计也可以实 ...
 - 关于Android中TextView显示多个空格
		
一.直接填写文字,输入多少,显示多少,如下: android:text="AAA AAA" ————————>显示:AAA AAA 二.通过设置str ...
 - [UGUI]图文混排(六):点击区域
		
点击区域可以分成两部分来分析: 0.Rect 搜索api:Rect和Rect.Rect,可以知道: 在GUI和GUILayout中,Rect的原点在左上角,向右为x轴正方向,向下为y轴正方向: 除此之 ...
 - HTML5[8]: 图文混排,图片与文字居中对齐
		
<img src="image.png"><span>999</span> img { /* ... */ vertical-align: t ...
 - 简单的Coretext 图文混排
		
在很多新闻类或有文字展示的应用中现在都会出现图文混排的界面例如网易新闻等,乍一看去相似一个网页,其实这样效果并非由UIWebView 加载网页实现.现在分享一种比较简单的实现方式 iOS sdk中为我 ...
 - CoreText实现图文混排之文字环绕及点击算法
		
系列文章: CoreText实现图文混排:http://www.jianshu.com/p/6db3289fb05d CoreText实现图文混排之点击事件:http://www.jianshu.co ...
 
随机推荐
- Nginx 是前端工程师的好帮手
			
Nginx [engine x] 是俄罗斯的 Igor Sysoev 编写的一个 强大的 HTTP 和反向代理服务器,而且也推出了 Windows 版本.Windows 版本使用 select 模型, ...
 - maven 编译解决jdk 版本问题
			
1.在父工程中pom 添加版本限制: <plugins> <plugin> <groupId>org.apache.maven.plugins</groupI ...
 - C++Builder 内存泄露检测
			
C++Builder 内存泄露检测 CodeGuard http://bbs.2cto.com/read.php?tid=179933 XE新版里 ReportMemoryLeaksOnShutdow ...
 - vb6 的关机代码
			
Public Const SE_PRIVILEGE_ENABLED As Integer = &H2Public Const TOKEN_QUERY As Integer = &H8P ...
 - manjaro 下golang protobuf的使用
			
1.下载protobuf compiler sudo pacman -S protobuf 2.添加环境变量GOBIN export GOBIN=~/go/bin 3.下载golang依赖的包 go ...
 - 【BZOJ4154】Generating Synergy【kd树】
			
题意 给定一棵以1为根的有根树,初始所有节点颜色为1,每次将距离节点a不超过l的a的子节点染成c,或询问点a的颜色 分析 我们以dfs序为横坐标,深度为纵坐标,建kd树.我们每次更新,都是在kd树中更 ...
 - JAVA - 守护线程(Daemon Thread)
			
转载自:http://www.cnblogs.com/luochengor/archive/2011/08/11/2134818.html 在Java中有两类线程:用户线程 (User Thread) ...
 - Python打包工具
			
打包Python应用,使用工具: 1.Linux和Windows下,使用pyinstaller pyinstaller -F -w XXX.py 在当前文件夹下生成两个文件夹:build .dist ...
 - [Selenium]计算坐标进行拖拽,重写dragAndDropOffset
			
//@author jzhang6 public void dragAndDropOffset(WebDriver driver,WebElement dragableEl, WebElement d ...
 - mysql导出导入sql文件方法(linux)
			
一.导入导出.sql文件for Linux: 1.从mysql中导出数据库test: 在终端运行:mysqldump -h localhost -u root -p test > /home/c ...