Android 自定义WebView 实现可以加载缓存数据
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](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>";
- // 纯图片 => 添加点击跳转,方便后期拦截
- //  => <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")
- @Override
- public 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;
- }
- @Override
- protected 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);
- }
- }
- }
2.2.然后如何动态加载WebView。
2.3.从缓存中获取字符串
这个body就是一些缓存的数据了。还要进行转换才能得到html。
3.局部分析
3.1.成员变量的定义
因为这里用到了将网页内容缓存。
所以缓存后的数据,特别是缓存后的图片就变成
这样的东西了
[texttext](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()删除之后就有影响了。可能这个只有在编辑模式下才需要这样设置的。
Android 自定义WebView 实现可以加载缓存数据的更多相关文章
- Spring Boot 启动以后然后再加载缓存数据 CommandLineRunner
实际应用中,我们会有在项目服务启动完成以后去加载一些数据或做一些事情(比如缓存)这样的需求. 为了解决这样的问题,Spring Boot 为我们提供了一个方法,通过实现接口 CommandLineRu ...
- Android项目框架之图片加载框架的选择
本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处! 从Android爆发以后,自定义的控件如EditTextWithDelete.ActionBar.P ...
- 控件WebView网页的加载
Android:控件WebView网页的加载 WebView可以使得网页轻松的内嵌到app里,还可以直接跟js相互调用. webview有两个方法:setWebChromeClient 和 setWe ...
- [MISSAJJ原创]cell内 通过SDWebImage自定义创建动态菊花加载指示器
最后更新已经放到了github上了 MISSAJJ自己写的一个基于SDWebImage自定义的管理网络图片加载的工具类(普通图片加载,渐现Alpha图片加载,菊花Indicator动画加载) 经常在项 ...
- android优化从网络中加载图片速度。。
从网络中加载图片主要要注意两个方面的问题: 1.内存管理:图片占的内存很大,假如图片数量多,很容易让系统抛出out of memory的异常. 同时我们也要注意不同android版本中内存管理的区别. ...
- Android引入高速缓存的异步加载全分辨率
Android引进高速缓存的异步加载全分辨率 为什么要缓存 通过图像缩放,我们这样做是对的异步加载优化的大图,但现在的App这不仅是一款高清大图.图.动不动就是图文混排.以图代文,假设这些图片都载入到 ...
- 浅试 Webview 一app 加载 H5小游戏
整体架构: InventionActivity:实现UI的实例化,基本的按钮Activity之间跳转 GameActivity:实现UI的实例化,Webview的基本使用 MyProgressDial ...
- Xamarin Android Fragment的两种加载方式
android Fragment的重点: 3.0版本后引入,即minSdk要大于11 Fragment需要嵌套在Activity中使用,当然也可以嵌套到另外一个Fragment中,但这个被嵌套的Fra ...
- Android 应用开发 之通过AsyncTask与ThreadPool(线程池)两种方式异步加载大量数据的分析与对比--转载
在加载大量数据的时候,经常会用到异步加载,所谓异步加载,就是把耗时的工作放到子线程里执行,当数据加载完毕的时候再到主线程进行UI刷新.在数据量非常大的情况下,我们通常会使用两种技术来进行异步加载,一 ...
随机推荐
- ArcGIS创建要素类
在使用ARCGIS软件进行工作时,免不了要建立地理数据库和要素类之类的.一下是我创建文件地理数据库并在数据库中创建要素类写相关步骤: 1.启动软件,可以使用ARCCatalog直接进行创建也可以使用A ...
- python_opencv应用系列1:图片读写
opencv的读写非常简单,主要用到的就是imread和imwrite两个函数 读取图片示例 import cv2 #imread(filename[, flags]) -> retval im ...
- 在IE中解决当前安全设置不允许下载该文件的方案
解决方案一: 1.0打开IE后,单击菜单栏中的“工具”菜单,在弹出的菜单中选择“Internet选项”命令: 2.0在弹出“Internet选项”的对话框中,打开“Internet选项”对话框: 3. ...
- mysql在控制台里出现中文问号问题
由于重装了wampserver,之前遇到的问题统统会重新出现,那么今天遇到的是在mysql控制台中,在表里输入中文数据,却出现问号的问题: 那么这个就跟编码有关系了,那么,我们就去wampserver ...
- 2017.11.12 web中JDBC 方式访问数据库的技术
JavaWeb------ 第四章 JDBC数据库访问技术 在JavaWeb应用程序中数据库访问是通过Java数据库连接(JavaDateBase Connectivity简称JDBC)数据库的链接一 ...
- IIS 处理程序“PageHandlerFactory-Integrated”
出现这种错误是因为先安装了.net framework 4.0然后才安装了iis,此种情况下iis默认只支持.net framewrok 2.0,要解决此问题,需要在iis中注册.net framew ...
- 【javascript】ajax 基础
什么是 ajax ajax 即“Asynchronous JavaScript and XML”(异步 JavaScript 和 XML),也就是无刷新数据读取. http 请求 首先需要了解 htt ...
- bootstarp v3 学习简记
1.快速设置浮动通过这两个class让页面元素左右浮动. !important被用来避免某些问题. <div class="pull-left">...</div ...
- margin与padding大比拼
用margin还是用padding这个问题相信是每个学css的人都想要去深入了解的. CSS边距属性定义元素周围的空间.通过使用单独的属性,可以对上.右.下.左的外边距进行设置.也可以使用简写的外边距 ...
- 使用winsw将spring-boot jar包注册成windows服务
背景:最近的项目中使用spring-boot, https://github.com/kohsuke/winsw/releases <service> <id>YJPSS< ...