TextView设置html标签内容

来源:互联网 发布:is私聊器软件isqt8 编辑:程序博客网 时间:2024/06/05 06:10

需求背景:
内容通知来自服务端的推送,因为不一样的活动需要,推送不一样的内容,内容的组成部分为html,都是前端的标签,可能有多个不同网址。
而app内,要使用TextView来显示html的内容,因为内容的不一样,以及内置的链接要适用跳转到app内的各个模块;
这里写图片描述

内容分析:
从需求来看,主要有以下几点注意:
1、活动内容不一致,html包含各种不同的格式;
2、内容都是html标签;
3、通知类型多,内含的网址可以跳到各个模块,这里就要求在识别网址时,要做分流;
4、一个通知可能含有几个不一样的网址;

技术分析:
1、在Android中Html.fromHtml()方法可以把Html标签内容转化为TextView所要显示的内容;
2、如何实现点击不同的链接可以跳转呢?一个TextView要实现内容可以点击,我们可以想到SpannableStringBuilder,设置setMovementMethod和setspan可以实现跳转了;
3、现在还有个攻克的难点,我怎么知道里面有多少条网址链接,我怎么知道点击哪个textview的哪个地方可以触发对应的链接呢?
查资料发现,html内容设置进去后,会set对应的setspan,这时候,我们可以使用
“URLSpan[] urls = sp.getSpans(0, end, URLSpan.class);”
来获取总共有多少个网址链接,在根据spanned匹配的开始和结束,我们能够知道怎么去响应对应的链接了;

具体代码如下:

** * Created by azhansy 2017/2/13. * 显示 HTML 的textView */public class HtmlTextView extends TextView {    public HtmlTextView(Context context) {        this(context, null);    }    public HtmlTextView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public HtmlTextView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        setMovementMethod(LocalLinkMovementMethod.getInstance());    }    public HtmlSpannableStringBuilder setHtmlText(String htmlText) {        return new HtmlSpannableStringBuilder(htmlText);    }    public static class LocalLinkMovementMethod extends LinkMovementMethod {        private static final long CLICK_DELAY = 500L;        private long lastClickTime;        static LocalLinkMovementMethod sInstance;        public static LocalLinkMovementMethod getInstance() {            if (sInstance == null)                sInstance = new LocalLinkMovementMethod();            return sInstance;        }        @Override        public boolean onTouchEvent(TextView widget, Spannable buffer,                                    MotionEvent event) {            int action = event.getAction();            if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) {                int x = (int) event.getX();                int y = (int) event.getY();                x -= widget.getTotalPaddingLeft();                y -= widget.getTotalPaddingTop();                x += widget.getScrollX();                y += widget.getScrollY();                Layout layout = widget.getLayout();                int line = layout.getLineForVertical(y);                int off = layout.getOffsetForHorizontal(line, x);                ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);                if (link.length != 0) {                    if (action == MotionEvent.ACTION_UP) {                        //长按 和 点击过快 不执行点击事件                        if (System.currentTimeMillis() - lastClickTime < CLICK_DELAY &&                                !Utils.isFastDoubleClick(1000L)) {                            link[0].onClick(widget);                        }                    } else {                        Selection.setSelection(buffer,                                buffer.getSpanStart(link[0]),                                buffer.getSpanEnd(link[0]));                        lastClickTime = System.currentTimeMillis();                    }                    return true;                } else {                    Selection.removeSelection(buffer);                    Touch.onTouchEvent(widget, buffer, event);                    return false;                }            }            return Touch.onTouchEvent(widget, buffer, event);        }    }    public class HtmlSpannableStringBuilder extends SpannableStringBuilder {        /**         * @param htmlLinkText         */        public HtmlSpannableStringBuilder(String htmlLinkText) {            updateClickSpan(htmlLinkText);        }        /**         * 更新Span         *         * @param htmlLinkText         */        private void updateClickSpan(String htmlLinkText) {            setText(Html.fromHtml(htmlLinkText));            CharSequence text = getText();            if (text instanceof Spannable) {                int end = text.length();                Spannable sp = (Spannable) getText();                URLSpan[] urls = sp.getSpans(0, end, URLSpan.class);                SpannableStringBuilder style = new SpannableStringBuilder(text);                style.clearSpans(); // should clear old spans                for (URLSpan url : urls) {                    // 设置Span                    int startSpan = sp.getSpanStart(url);                    int endSpan = sp.getSpanEnd(url);                    if (startSpan >= 0) {                        style.setSpan(new Clickable(new URLClickListener(url.getURL())), startSpan, endSpan, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);                    }                    Logger.d("azhansy: 链接", url.getURL());                }                setText(style);            }        }        //TextView中的Span区域点击事件        class Clickable extends ClickableSpan implements View.OnClickListener {            private final View.OnClickListener mListener;            public Clickable(View.OnClickListener l) {                mListener = l;            }            @Override            public void onClick(View widget) {                mListener.onClick(widget);            }            @Override            public void updateDrawState(TextPaint ds) {                super.updateDrawState(ds);                ds.setUnderlineText(false);                ds.setColor(Color.parseColor("#556B95"));            }        }        private class URLClickListener implements View.OnClickListener {            private String url;            URLClickListener(String url) {                this.url = url;            }            @Override            public void onClick(View arg0) {                Logger.d("azhansy: 点击后的链接 ", url);               //这里可以分流点击的链接                    }                }            }        }    }}
0 0