1.自定义WebView说明

1.1.这个WebView可以加载缓存的数据。(需要后端配合,将html转换成一个字符串,主要是图片要用特殊格式)

1.2.注入了图片链接,为了方便点击webView中的图片而跳转。

1.3.这是一个FrameLayout动态加载的WebView,布局中没有任何声明这个WebView。

2.源代码及应用

2.1.源代码如下,可以直接Copy。

public class MarkdownView extends WebView {private static final String TAG = MarkdownView.class.getSimpleName();// 带有点击的图片 => 为了防止被转换,提前转化为 html// [text ![text](image_url) text](link) => <a href="link" ><img src="data:image_url" /></a>private static final String IMAGE_LINK_PATTERN = "\\[(.*)!\\[(.*)\\]\\((.*)\\)(.*)\\]\\((.*)\\)";private static final String IMAGE_LINK_REPLACE = "<a href=\"$5\" >$1<img src=\"$3\" />$4</a>";// 纯图片 => 添加点击跳转,方便后期拦截// ![text](image_url) => <img class="gcs-img-sign" src="data:image_url" />private static final String IMAGE_PATTERN = "!\\[(.*)\\]\\((.*)\\)";private static final String IMAGE_REPLACE = "<img class=\"gcs-img-sign\" src=\"$2\" />";private String mPreviewText;public MarkdownView(Context context) {this(context, null);}public MarkdownView(Context context, AttributeSet attrs) {this(context, attrs, 0);}@SuppressLint({"AddJavascriptInterface", "SetJavaScriptEnabled"})public MarkdownView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);if (isInEditMode()) {return;}WebSettings settings = getSettings();settings.setJavaScriptEnabled(true);settings.setDomStorageEnabled(true);settings.setDatabaseEnabled(true);initialize();}private void initialize() {loadUrl("file:///android_asset/html/preview.html");if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {getSettings().setAllowUniversalAccessFromFileURLs(true);}if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);}setWebChromeClient(new WebChromeClient() {@SuppressLint("JavascriptInterface")@Overridepublic void onProgressChanged(WebView view, int newProgress) {super.onProgressChanged(view, newProgress);if (newProgress == 100) {if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {loadUrl(mPreviewText);} else {evaluateJavascript(mPreviewText, null);}}}});}public void loadMarkdownFromFile(File markdownFile) {String mdText = "";try {FileInputStream fileInputStream = new FileInputStream(markdownFile);InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);BufferedReader bufferedReader = new BufferedReader(inputStreamReader);String readText;StringBuilder stringBuilder = new StringBuilder();while ((readText = bufferedReader.readLine()) != null) {stringBuilder.append(readText);stringBuilder.append("\n");}fileInputStream.close();mdText = stringBuilder.toString();} catch (FileNotFoundException e) {Log.e(TAG, "FileNotFoundException:" + e);} catch (IOException e) {Log.e(TAG, "IOException:" + e);}setMarkDownText(mdText);}public void loadMarkdownFromAssets(String assetsFilePath) {try {StringBuilder buf = new StringBuilder();InputStream json = getContext().getAssets().open(assetsFilePath);BufferedReader in = new BufferedReader(new InputStreamReader(json, "UTF-8"));String str;while ((str = in.readLine()) != null) {buf.append(str).append("\n");}in.close();setMarkDownText(buf.toString());} catch (IOException e) {e.printStackTrace();}}public void setMarkDownText(String markdownText) {String injectMdText = injectImageLink(markdownText);String escMdText = escapeForText(injectMdText);if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {mPreviewText = String.format("javascript:preview('%s')", escMdText);} else {mPreviewText = String.format("preview('%s')", escMdText);}initialize();}/*** 注入图片链接*/private String injectImageLink(String mdText) {// TODO 修复代码区md格式图片被替换问题mdText = mdText.replaceAll(IMAGE_LINK_PATTERN, IMAGE_LINK_REPLACE);mdText = mdText.replaceAll(IMAGE_PATTERN, IMAGE_REPLACE);return mdText;}private String escapeForText(String mdText) {String escText = mdText.replace("\n", "\\\\n");escText = escText.replace("'", "\\\'");escText = escText.replace("\r", "");return escText;}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);if (isInEditMode()) {canvas.drawColor(Color.WHITE);canvas.translate(canvas.getWidth() / 2, 30);Paint paint = new Paint();paint.setTextAlign(Paint.Align.CENTER);paint.setTextSize(30);paint.setColor(Color.GRAY);canvas.drawText("MarkdownView", -30, 0, paint);}}
}

View Code

2.2.然后如何动态加载WebView。

  

2.3.从缓存中获取字符串

  

  这个body就是一些缓存的数据了。还要进行转换才能得到html。

3.局部分析

3.1.成员变量的定义

  

  因为这里用到了将网页内容缓存。

  所以缓存后的数据,特别是缓存后的图片就变成

  ![text](image_url)这样的东西了

  [text![text](image_url)text](link)这样的东西了

  然后需要替换成原始的html。所以就用到了2个模板来替换。

  private String mPreviewText; 就是缓存的html内容。

3.2.有三个构造函数

  一个参数的构造函数

  

  

  两个参数的构造函数

  

  三个参数的构造函数

  

  这是最重要的构造函数。

  setJavaScriptEnabled(true)==>支持js

  setDomStorageEnabled(true)==>开启DOM storage API功能

  setDatabaseEnabled(true)==>开启database storage API功能

3.3.初始化函数initialize()

  

  首先加载本地文件(file://android_asset/html/preview.html)

  为了防止webView加载一些链接出现白板现象

  这里需要判断一下如果SDK>=16,需要设置:

    getSettings().setAllowUniversalAccessFromFileURLs(true);

  为了防止加载https的URL时在5.0以上加载不了,5.0以下可以加载,SDK>=21,需要设置:

    getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);

  然后设置一个新的WebChromeClient

    当newProgress到百分之百了,需要判断SDK<19

    小于19的话,执行loadUrl(缓存text);

    大于19的话,执行evaluateJavascript(缓存text,null);==>专门用于异步调用javascript方法,有一个回调。

    

3.4.加载一个缓存文件

  

  作用就是:先从一个文件中读取字符,存放到一个字符串中,然后再调用setMarkDownText(字符串);

3.5.加载一个缓存资源

  

  作用:从应用的资源文件中获取字符流,然后转换成字符串。

3.6.将缓存数据替换成html标签

  

  首先是将图片替换成正常的html

  然后是将一些制表符、换行符替换成正常的html

  最后再执行初始化函数。

3.7.注入图片链接,将图片翻译成正常的html

  

3.8.将换行符,特殊字符,翻译成正常的html

  

3.9.重写WebView的onDraw函数

   重画WebView的界面。

  

  这个函数估计没什么用,我注释掉以及修改代码都没有反应。

  但是我将isInEditMode()删除之后就有影响了。可能这个只有在编辑模式下才需要这样设置的。

转载于:https://www.cnblogs.com/Jason-Jan/p/7921004.html

Android 自定义WebView 实现可以加载缓存数据相关推荐

  1. UNI-APP在自定义组件中内嵌H5/Html网页,可自定义webview大小,加载不闪屏

    问题描述: UNI-APP在自定义组件中内嵌H5/Html网页时,通过内置组件 web-view 实现(如下),发现会自动铺满整个页面,不可控制大小(默认充满屏幕不可控制大小) <web-vie ...

  2. android 标题栏进度圈使用方法,Android 自定义标题栏 显示网页加载进度的方法实例...

    这阵子在做Lephone的适配,测试组提交一个bug:标题栏的文字较长时没有显示完全,其实这并不能算个bug,并且这个问题在以前其他机器也没有出现,只是说在Lephone的这个平台上显示得不怎么美观, ...

  3. Android自定义简单的图片加载器(ImageLoader)

    废话不多述,首先来说明下 为什么要用图片加载器 呢,就是为了避免图片重复从网络加载.也就是在第一次从网络加载之后就把图片缓存在本地,下次用的时候直接从本地查找,有的话就直接用,没有再从网络加载. 加载 ...

  4. Android使用webview控件加载本地html,通过Js与后台Java实现数据的传递

    1.在布局文件中加WebView控件,在java中获取WebView对象. 2.加载本地html文件. webView.loadUrl("file:///android_asset/andr ...

  5. Android网络图片加载缓存处理库的使用---第三方库学习笔记(五)

    两款比较优秀的开源图片处理库框架:Universal-ImageLoader和Picasso. Universal-ImageLoader 简介: Universal-ImageLoader是目前An ...

  6. android web canvas,HTML5 - Canvas无法在Android WebView的第一次加载时渲染

    我正在开发基于HTML5画布的游戏,该游戏在现有应用程序的WebView中运行.在第一次运行游戏时,它会在后台成功加载,所有日志都表明它已准备就绪并正在运行.但是,WebView中不显示任何内容.如果 ...

  7. Android中使用x5内核加载网页的实现

    前言 联系方式 背景 SDK下载 SDK集成 使用 代码实现 前言 由于是使用的腾讯浏览服务,所以这里大部分介绍的是官网的一些东西,不过自己会做一些复杂使用部分的实现,不至于像官网上介绍的笼统. 联系 ...

  8. 打造自己的图片加载缓存库(Picasso OR Glide)

    好久没写文章了,一个是工作的原因,还一个就是这几个月看了很多文章,一直在补充自己的知识.之前看到一句很喜欢的话--感到快乐就忙东忙西,感到累了就放空自己,这几个月一"快乐"了,就停 ...

  9. android SwipeRefreshLayout 增加上拉加载更多

    2019独角兽企业重金招聘Python工程师标准>>> 大家可能有的没有swipeRefreshLayout这个类,简单说一下,这是v4包里面的,19.1版本的时候就有了,但是当时的 ...

最新文章

  1. CentOS 7 搭建docker仓库
  2. 控制器框架Struts与策略模式那点事
  3. 顺序表的结构和9个基本运算算法
  4. requests模拟登陆 验证码
  5. [Swust OJ 85]--单向公路(BFS)
  6. [转]其实每个男孩都想做一个感情专一的好男人
  7. 红帽yum安装httpd出现错误(This system is not registered to Red Hat Subscription Management. You can use subs)
  8. Windows下FFmpeg各版本库文件下载
  9. python优秀源码新闻系统_[内附完整源码和文档] 基于python的新闻检索系统
  10. 算法-罗马数字转成整数(leetcode13)
  11. hcl启动设备失败_水电站,黑启动是什么?
  12. python 对任意文件(jpg,png,mp3,mp4)base64的编码解码
  13. 抑郁症自测量表测试软件,抑郁自评:医用抑郁自测量表,快来测一测你的抑郁指数是多少...
  14. GetDC和BeginPaint
  15. 【小程序专栏】总结uniapp开发小程序的开发规范
  16. Chrome 屏蔽https中访问http(不安全内容)
  17. JavaScript:实现加密哈希SHA-256 算法(附完整源码)
  18. 小学数学与计算机整合课优质教案,小学数学优质课教案《长方形的面积》(通用5篇)...
  19. 1.试用期个人工作总结(篇一)
  20. 视频会议检测不到摄像头,电脑打开相关功能提示无法使用-驱动人生解决方案

热门文章

  1. Oracle 存储结构_表空间简介
  2. 中科大量子计算机重大突破,中国科大在量子计算研究中获重大突破
  3. ios 登录 java 后台,IOS苹果登录sign in with apple后端校验
  4. c++和c语言的区别_C 语言和 C++ 有什么区别?老程序员居然这样理解,不怕你不懂...
  5. python注释以符号什么开始_python注释以什么符号开始
  6. html如何找寻vue文件,如何预览vue文件
  7. iphone屏蔽系统更新_iPhone手机经常提示更新系统,教你一招关闭方法,学到了
  8. 指向成员函数的指针有什么用_指针函数,函数指针,有点懵圈了?你能分清楚吗...
  9. 为什么只有三次挥手_TCP为什么是三次握手,为什么不是两次或四次,TCP四次挥手...
  10. oracle服务器错误,oracle 11g数据库维护中错误总结