zoukankan      html  css  js  c++  java
  • 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之后,则需要实现图文混排就轻而易举了

    1. MyImageGetter imageGetter = new MyImageGetter(this, contentTextView);  

    2. 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());  



    网易云产品免费体验馆,无套路试用,零成本体验云计算价值。  

    本文来自网易云社区,经作者戚明峰授权发布


    相关文章:
    【推荐】 为何要在网站上设置的验证码
    【推荐】 qemu+kvm的IO路径分析

  • 相关阅读:
    python爬虫23 | 手机,这次要让你上来自己动了。这就是 Appium+Python 的牛x之处
    python爬虫22 | 以后我再讲python「模拟登录」我就是狗
    python爬虫21 | 对于b站这样的滑动验证码,不好意思,照样自动识别
    phpcms 之 日期时间标签的调用
    phpcms 友情链接的调用
    在网页中嵌入百度地图的步骤(转)
    jquery 怎么取select选中项 自定义属性的值
    PHP实现根据银行卡号判断银行
    数据库基础
    从输入网址到显示网页的过程中发生了什么?(转自88旧港)
  • 原文地址:https://www.cnblogs.com/163yun/p/9662063.html
Copyright © 2011-2022 走看看