Android中的富文本

Android开发在与后台对接的时候,有时会返回HTML5格式的数据,需要解析<p><p/><image></image>标签,比如如下返回数据:

        <p style="margin: 0pt;"></p>
        <p style="margin: 0pt;"></p>
        <p style="margin: 0pt;">
            <span style='color: rgb(0, 0, 0); font-family: 宋体; font-size: 12pt; mso-spacerun: "yes"; mso-font-kerning: 1.0000pt;'><font face="宋体">领导者的综合影响力主要来源于()<span style='font-family: 宋体; font-size: 12pt; font-weight: normal; mso-spacerun: "yes"; mso-font-kerning: 1.0000pt;'><font face="宋体">。</font></span></font></span>
        </p>
        <p>
            <br>
        </p>

还有带网络图片的图片的,如:


Android_image_influter.png

我们就需要用到富文本来解析了,具体使用如下:
将html代码转换为text,然后显示在textview中呢,有一个简单直接的方法:

textView.setText(Html.fromHtml(content));

用的时候却发现html里面的图片没法被被解析出来,对于图片Html还有一个方法:

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

这里面需要我们自定义imageGetter,这个对象是用于解析html中的图片.

public class MImageGetter implements Html.ImageGetter {
    private Context c;
    private TextView container;

    public MImageGetter(TextView text, Context c) {
        this.c = c;
        this.container = text;
    }

    @Override
    public Drawable getDrawable(String source) {
        Drawable drawable = null;
        InputStream is = null;
        //source便是图片的路径,如果图片在本地,可以这样做        
        is = c.getResources().getAssets().open(source);
try {
            TypedValue typedValue = new TypedValue();
            typedValue.density = TypedValue.DENSITY_DEFAULT;
            drawable = Drawable.createFromResourceStream(null, typedValue, is, "src");
            drawable.setBounds(0, 0, drawable.getIntrinsicWidth(),
                               drawable.getIntrinsicHeight());
            return drawable;
        } catch (Exception e) {
            System.out.println(e);
            return null;
        }
    }

最终这样调用:

textView.setText(Html.fromHtml(text, new MImageGetter(textView, this), null));

这样便可以实现图文混排了,在该显示图片的地方显示图片。
如果是要显示网络上的图片,getDrawable方法可以这样

public Drawable getDrawable(String source) {
         final LevelListDrawable drawable = new LevelListDrawable();
         Glide.with(c).load(source).asBitmap().into(new SimpleTarget<Bitmap>() {
             @Override
             public void onResourceReady(Bitmap resource,  
                      GlideAnimation<? super Bitmap> glideAnimation) {
                 if(resource != null) {
                     BitmapDrawable bitmapDrawable = new BitmapDrawable(resource);
                     drawable.addLevel(1, 1, bitmapDrawable);
                     drawable.setBounds(0, 0, resource.getWidth(),resource.getHeight());
                     drawable.setLevel(1);
                     container.invalidate();
                     container.setText(container.getText());
                 }
             }
         });
         return drawable;
        }

第三个参数 其作用是把 HTML 带标记的文本内容字符串转化成可以显示效果的Spanned 字符串 。由于并非所有的 HTML 标签都可以转化,所以在使用时,用户需要自己添加一些必要的标签和处理方法时才会使用的.
对于Android中有些还要求具有点击事件的功能,就需要自定义个 LinkMovementMethodExt类,那么代码如下:

public class LinkMovementMethodExt extends LinkMovementMethod {
    private static LinkMovementMethod sInstance;
    private  Handler handler = null;
    private  Class spanClass = null;
    
    public static  MovementMethod getInstance(Handler _handler,Class _spanClass) {
        if (sInstance == null) {
            sInstance = new LinkMovementMethodExt();
            ((LinkMovementMethodExt)sInstance).handler = _handler;
            ((LinkMovementMethodExt)sInstance).spanClass = _spanClass;
        }
 
        return sInstance;
    }
    
    int x1;
    int x2;
    int y1;
    int y2;
    
     @Override
        public boolean onTouchEvent(TextView widget, Spannable buffer,
                                    MotionEvent event) {
            int action = event.getAction();
 
            if (event.getAction() == MotionEvent.ACTION_DOWN){
                x1 = (int) event.getX();
                y1 = (int) event.getY();
            }
            
            if (event.getAction() == MotionEvent.ACTION_UP) {
                x2 = (int) event.getX();
                y2 = (int) event.getY();
                
            if (Math.abs(x1 - x2) < 10 && Math.abs(y1 - y2) < 10) {
                x2 -= widget.getTotalPaddingLeft();
                y2 -= widget.getTotalPaddingTop();
                x2 += widget.getScrollX();
                y2 += widget.getScrollY();
                Layout layout = widget.getLayout();
                int line = layout.getLineForVertical(y2);
                int off = layout.getOffsetForHorizontal(line, x2);
                /**
                 * get you interest span
                 */
                Object[] spans = buffer.getSpans(off, off, spanClass);
                if (spans.length != 0) {
                    
                    Selection.setSelection(buffer,
                            buffer.getSpanStart(spans[0]),
                            buffer.getSpanEnd(spans[0]));
                    MessageSpan obj = new MessageSpan();
                    obj.setObj(spans);
                    obj.setView(widget);
                    Message message = handler.obtainMessage();
                    message.obj = obj;
                    message.what = 200;
                    message.sendToTarget();
                    return true;
                }
            }
            }
            //return false; 
            return super.onTouchEvent(widget, buffer, event);
            
         
        }
 
        
        
     public boolean canSelectArbitrarily() {
            return true;
        }
     
    public boolean onKeyUp(TextView widget, Spannable buffer, int keyCode,
            KeyEvent event) {
        return false;
    }

MessageSpan类如下:

public class MessageSpan {
    private Object obj;
    private TextView view;
 
    public Object getObj() {
        return obj;
    }
 
    public void setObj(Object obj) {
        this.obj = obj;
    }
 
    public TextView getView() {
        return view;
    }
 
    public void setView(TextView view) {
        this.view = view;
    }
}

页面及使用代码如下:

public class MyTestActivity extends BaseActivity {
    TextView tv;
    private String content;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my_test);
        tv = findViewById(R.id.tv);
    }
    @Override
    protected void initData(Bundle savedInstanceState) {
        content = "1、找出下图中所有轴对称图形,它们是(  )。\n" +
                "A、<img src=\"http://XXXXXXX//XXXX/TextEditor/eWebEditor/uploadfile/2016/06/20160613195331478.png\" border=\"0\" align=\"absmiddle\">\n" +
                "B、<img src=\"http://XXXXXXX//XXXX/TextEditor/eWebEditor/uploadfile/2016/06/20160613195406586.png\" border=\"0\" align=\"absmiddle\">\n" +
                "C、<img src=\"http://XXXXXXX//XXXX/TextEditor/eWebEditor/uploadfile/2016/06/20160613195417277.png\" border=\"0\" align=\"absmiddle\">\n"+
                "D、<img src=\"http://XXXXXXX//XXXX/TextEditor/eWebEditor/uploadfile/2016/06/20160613195426887.png\" border=\"0\" align=\"absmiddle\">";
        tv.setText(Html.fromHtml(content, new MImageGetter(tv, getApplicationContext()), null));
        final Handler handler = new Handler() {
            public void handleMessage(Message msg) {
                int what = msg.what;
                if (what == 200) {
                    MessageSpan ms = (MessageSpan) msg.obj;
                    Object[] spans = (Object[]) ms.getObj();
                    final ArrayList<String> list = new ArrayList<>();
                    for (Object span : spans) {
                        if (span instanceof ImageSpan) {
                            Log.i("picUrl==", ((ImageSpan) span).getSource());
                            list.add(((ImageSpan) span).getSource());
                            Intent intent = new Intent(getApplicationContext(), ImageGalleryActivity.class);
                            intent.putStringArrayListExtra("images", list);
                            startActivity(intent);
                        }
                    }
                }
            }
        };
        tv.setMovementMethod(LinkMovementMethodExt.getInstance(handler, ImageSpan.class));
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容