美文网首页Android程序员
使用webview处理富文本显示

使用webview处理富文本显示

作者: 吃泥巴的猫 | 来源:发表于2019-01-25 17:03 被阅读16次

    显示富文本开始使用了RichText的三方库,之后发现对样式支持度比较低,之后开始考虑使用webview来进行加载,通过重写webview并增加js来处理进行图片点击等操作的实现。
    懒懒的。。。不想打那么多字。。。直接复制代码吧。。。
    用jsoup解析html。。。
    依赖 org.jsoup:jsoup:1.11.3
    调用方法:

    tvHtml.imageClick((imageUrls, position) -> {
                            //imageUrls是所有图片地址的list
                            ///position是点击位置
                    })
                    .urlClick(url -> {
                            //url为链接跳转地址
                            //返回true为自己处理跳转,false为webview自行跳转
                            return true;
                    })
                    .imageLongClick(imageUrl->{
                            //imageUrl为长按图片的地址
                    })
                    .setHtml(html);//html富文本的字符串
    

    在xml中加入
    控件不可滑动。。。请加在可滑动控件内

    <HtmlView
            android:id="@+id/tv_html"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="14sp" />
    

    显示富文本的webview类封装

    public class HtmlView extends WebView {
    
        private List<String> listImgSrc = new ArrayList<>();
    
        public void setHtml(String html){
            loadDataWithBaseURL("", html, "text/html", "UTF-8", "");
        }
    
        public HtmlView(Context context) {
            super(context);
            init(context);
        }
    
        public HtmlView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init(context);
        }
    
        public HtmlView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init(context);
        }
    
        @SuppressLint({"SetJavaScriptEnabled", "AddJavascriptInterface"})
        private void init(Context context) {
            this.getSettings().setJavaScriptEnabled(true);
            this.getSettings().setDefaultTextEncodingName("UTF -8");
            this.setHorizontalScrollBarEnabled(false);//水平不显示
            this.setVerticalScrollBarEnabled(false); //垂直不显示
            this.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY); //取消滚动条白边效果
            this.getSettings().setUseWideViewPort(true);
            this.getSettings().setLoadWithOverviewMode(true);
            this.getSettings().setJavaScriptEnabled(true);
            this.getSettings().setDefaultTextEncodingName("UTF -8");
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
                this.getSettings().setMixedContentMode(WebSettings
                        .MIXED_CONTENT_ALWAYS_ALLOW);  //注意安卓5.0以上的权限
            //载入js
            this.addJavascriptInterface(new MyJavascriptInterface(context), "imageListener");
            //获取 html
            this.addJavascriptInterface(new InJavaScriptLocalObj(), "local_obj");
            this.setWebViewClient(new WebViewClient() {
                // 网页跳转
                @Override
                public boolean shouldOverrideUrlLoading(WebView view, String url) {
                    if (url != null && !url.isEmpty() && onUrlClickListener != null) {
                        return onUrlClickListener.urlClicked(url);
                    } else return true;
                }
    
                // 网页加载结束
                @Override
                public void onPageFinished(WebView view, String url) {
                    super.onPageFinished(view, url);
                    // web 页面加载完成,添加监听图片的点击 js 函数
                    HtmlView.this.setImageClickListner();
                    //解析 HTML
                    HtmlView.this.parseHTML(view);
                }
    
                @Override
                public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
    
                }
            });
            this.setOnLongClickListener(v -> {
                setWebImageLongClickListener(v);
                return false;
            });
        }
        /**
         * 响应长按点击事件
         * @param v
         */
        private void setWebImageLongClickListener(View v) {
            if (v instanceof WebView) {
                HitTestResult result = ((WebView) v).getHitTestResult();
                if (result != null) {
                    int type = result.getType();
                    if (type == HitTestResult.IMAGE_TYPE || type == HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {
                        if(imageLongClickListener!=null){
                            imageLongClickListener.imageLongClicked(result.getExtra());
                        }
                    }
                }
            }
        }
        /**
         * 解析 HTML 该方法在 setWebViewClient 的 onPageFinished 方法中进行调用
         *
         * @param view
         */
        private void parseHTML(WebView view) {
            view.loadUrl("javascript:window.local_obj.showSource('<head>'+"
                    + "document.getElementsByTagName('html')[0].innerHTML+'</head>');");
        }
    
        /**
         * 注入 js 函数监听,这段 js 函数的功能就是,遍历所有的图片,并添加 onclick 函数,实现点击事件,
         * 函数的功能是在图片点击的时候调用本地java接口并传递 url 过去
         */
        private void setImageClickListner() {
            // 这段js函数的功能就是,遍历所有的img几点,并添加onclick函数,函数的功能是在图片点击的时候调用本地java接口并传递url过去
            this.loadUrl("javascript:(function(){" +
                    "var objs = document.getElementsByTagName(\"img\"); " +
                    "for(var i=0;i<objs.length;i++)  " +
                    "{"
                    + "    objs[i].onclick=function()  " +
                    "    {  "
                    + "        window.imageListener.startShowImageActivity(this.src);  " +
                    "    }  " +
                    "}" +
                    "})()");
        }
    
        // js 通信接口,定义供 JavaScript 调用的交互接口
        private class MyJavascriptInterface {
            private Context context;
    
            public MyJavascriptInterface(Context context) {
                this.context = context;
            }
    
    
            @android.webkit.JavascriptInterface
            public void startShowImageActivity(String url) {
                for (int i = 0; i < listImgSrc.size(); i++) {
                    if (listImgSrc.get(i).equals(url)){
                        imageClickListener.imageClicked(listImgSrc, i);
                        break;
                    }
                }
            }
        }
    
        /**
         * 图片点击回调
         *
         * @param imageClickListener 回调
         * @return RichTextConfigBuild
         */
        public HtmlView imageClick(OnImageClickListener imageClickListener) {
            this.imageClickListener = imageClickListener;
            return this;
        }
    
        private OnImageClickListener imageClickListener;
    
        public interface OnImageClickListener {
            /**
             * 图片被点击后的回调方法
             *
             * @param imageUrls 本篇富文本内容里的全部图片
             * @param position  点击处图片在imageUrls中的位置
             */
            void imageClicked(List<String> imageUrls, int position);
        }
        /**
         * 图片长按回调
         *
         * @param imageLongClickListener 回调
         * @return RichTextConfigBuild
         */
        public HtmlView imageLongClick(OnImageLongClickListener imageLongClickListener) {
            this.imageLongClickListener = imageLongClickListener;
            return this;
        }
    
        private OnImageLongClickListener imageLongClickListener;
    
        public interface OnImageLongClickListener {
            /**
             * 图片被长按后的回调方法
             *
             * @param imageUrl 长按图片地址
             */
            void imageLongClicked(String imageUrl);
        }
        /**
         * 链接点击回调
         *
         * @param onUrlClickListener 回调
         * @return RichTextConfigBuild
         */
        public HtmlView urlClick(OnUrlClickListener onUrlClickListener) {
            this.onUrlClickListener = onUrlClickListener;
            return this;
        }
    
        private OnUrlClickListener onUrlClickListener;
    
        public interface OnUrlClickListener {
    
            /**
             * 超链接点击得回调方法
             *
             * @param url 点击得url
             * @return true:已处理,false:未处理(会进行默认处理)
             */
            boolean urlClicked(String url);
        }
    
        private class InJavaScriptLocalObj {
            /**
             * 获取要解析 WebView 加载对应的 Html 文本
             *
             * @param html WebView 加载对应的 Html 文本
             */
            @android.webkit.JavascriptInterface
            public void showSource(String html) {
                //从 Html 文件中提取页面所有图片对应的地址对象
                listImgSrc = getImgSrc(html);
            }
        }
    
        private List<String> getImgSrc(String htmlStr) {
            Document document = Jsoup.parse(htmlStr);
            Elements images = document.select("img[src~=(?i)\\.(png|jpe?g|gif)]");
            List<String> pics = new ArrayList<>();
            for (Element image : images) {
                pics.add(image.attr("src"));
            }
            return pics;
        }
    
        //重写onScrollChanged 方法
        @Override
        protected void onScrollChanged(int l, int t, int oldl, int oldt) {
            super.onScrollChanged(l, t, oldl, oldt);
            scrollTo(0, 0);
        }
    }
    

    相关文章

      网友评论

        本文标题:使用webview处理富文本显示

        本文链接:https://www.haomeiwen.com/subject/nxhvjqtx.html