WebView网页加载器详解

现在混合开发越来越火热,WebView的使用也是越来越频繁,今天详细介绍一下webview的常用属性和方法,以及开发时遇到的坑

使用

xml中定义

<WebView
        android:id="@+id/main_webview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layerType="software"
        android:fadingEdge="none"
        android:fadingEdgeLength="0dp"
        android:scrollbars="none"/>

android:layerType="software"硬件加速 layerType与WebView白屏
android:fadingEdge="none"设置拉滚动条时 ,边框渐变的放向。none(边框颜色不变),horizontal(水平方向颜色变淡),vertical(垂直方向颜色变淡)。
android:fadingEdgeLength="0dp"用来设置边框渐变的长度
android:scrollbars="none"去掉webview的滚动条

加载html的四种方式

  • 网络url
    webView.loadUrl("https://blog.csdn.net/zyw0101");
    注:如果页面加载后自动跳转默认浏览器,则需要webView.setWebViewClient(new WebViewClient());,下面会详细介绍
  • assets文件下的html
    webView.loadUrl("file:///android_asset/my.html");
  • sd卡中的html
    webView.loadUrl("file:///" + Environment.getExternalStorageDirectory() + "/my.html");
    注:访问本地文件需要设置setAllowFileAccess为true,同时开启读取权限
  • 直接显示html代码
    webView.loadDataWithBaseURL(null, "<!DOCTYPE html>\n" + "<html>\n" + "<head>\n" + "\t<title>测试网页</title>\n" + "</head>\n" + "<body>\n" + "<p>直接显示html代码</p>\n" + "</body>\n" + "</html>", "text/html", "utf-8", null);

WebSetting常用设置

        WebSettings webSettings = webView.getSettings();
        webSettings.setDomStorageEnabled(true);// 开启 DOM storage API 功能
        webSettings.setLoadWithOverviewMode(true); // 当页面宽度大于WebView宽度时,缩小使页面宽度等于WebView宽度
        webSettings.setUseWideViewPort(true);// 页面通过`<meta name="viewport" ... />`自适应手机屏幕
        webSettings.setJavaScriptEnabled(true);// 支持JS
        webSettings.setAllowContentAccess(true);// 是否可访问Content Provider的资源,默认值 true
        webSettings.setAllowFileAccess(true);// 是否可访问本地文件 如:读取sd卡的html文件
        webSettings.setAllowFileAccessFromFileURLs(false);// 是否允许通过file url加载的Javascript读取本地文件,默认值 false
        webSettings.setAllowUniversalAccessFromFileURLs(false);// 是否允许通过file url加载的Javascript读取全部资源(包括文件,http,https),默认值 false
        webSettings.setSupportZoom(true);// 支持屏幕缩放
        webSettings.setBuiltInZoomControls(true);// 支持屏幕缩放
        webSettings.setDisplayZoomControls(false);// 显示隐藏缩放按钮
        webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);// 缓存方式

不常用

// 定位(location)
settings.setGeolocationEnabled(true);

// 是否保存表单数据
settings.setSaveFormData(true);

// 是否当webview调用requestFocus时为页面的某个元素设置焦点,默认值 true
settings.setNeedInitialFocus(true);  

// 布局算法
settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL);

// 是否支持多窗口,默认值false
settings.setSupportMultipleWindows(false);

// 是否可用Javascript(window.open)允许弹窗,默认值 false
settings.setJavaScriptCanOpenWindowsAutomatically(false);

// 资源加载
settings.setLoadsImagesAutomatically(true); // 是否自动加载图片
settings.setBlockNetworkImage(false);       // 禁止加载网络图片
settings.setBlockNetworkLoads(false);       // 禁止加载所有网络资源

// 默认文本编码,默认值 "UTF-8"
settings.setDefaultTextEncodingName("UTF-8");
settings.setDefaultFontSize(16);        // 默认文字尺寸,默认值16,取值范围1-72
settings.setDefaultFixedFontSize(16);   // 默认等宽字体尺寸,默认值16
settings.setMinimumFontSize(8);         // 最小文字尺寸,默认值 8
settings.setMinimumLogicalFontSize(8);  // 最小文字逻辑尺寸,默认值 8
settings.setTextZoom(100);              // 文字缩放百分比,默认值 100

// 字体
settings.setStandardFontFamily("sans-serif");   // 标准字体,默认值 "sans-serif"
settings.setSerifFontFamily("serif");           // 衬线字体,默认值 "serif"
settings.setSansSerifFontFamily("sans-serif");  // 无衬线字体,默认值 "sans-serif"
settings.setFixedFontFamily("monospace");       // 等宽字体,默认值 "monospace"
settings.setCursiveFontFamily("cursive");       // 手写体(草书),默认值 "cursive"
settings.setFantasyFontFamily("fantasy");       // 幻想体,默认值 "fantasy"

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    // 用户是否需要通过手势播放媒体(不会自动播放),默认值 true
    settings.setMediaPlaybackRequiresUserGesture(true);
}

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    // 5.0以上允许加载http和https混合的页面(5.0以下默认允许,5.0+默认禁止)
    settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    // 是否在离开屏幕时光栅化(会增加内存消耗),默认值 false
    settings.setOffscreenPreRaster(false);
}

if (isNetworkConnected(context)) {
    // 根据cache-control决定是否从网络上取数据
    settings.setCacheMode(WebSettings.LOAD_DEFAULT);
} else {
    // 没网,离线加载,优先加载缓存(即使已经过期)
    settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
}

// 提高渲染的优先级
settings.setRenderPriority(WebSettings.RenderPriority.HIGH);

WebView的常用方法

  • WebViewClient

  • 主要帮助WebView处理各种通知、请求事件的,有以下常用方法:

    • onPageFinished 页面请求完成
    • onPageStarted 页面开始加载
    • shouldOverrideUrlLoading 拦截url
    • onReceivedError 访问错误时回调,例如访问网页时报错404,在这个方法回调的时候可以加载错误页面。
webView.setWebViewClient(new WebViewClient(){
            // 拦截url
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
                // 拦截页面加载,返回true表示宿主app拦截并处理了该url,否则返回false由当前WebView处理
                // 该方法可以防止跳转默认浏览器
                return super.shouldOverrideUrlLoading(view, request);
            }
            // 页面开始加载
            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                super.onPageStarted(view, url, favicon);
                Log.e(TAG, "onPageStarted");
                progressBar.setVisibility(View.VISIBLE);
            }

            // 页面加载完成
            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                Log.e(TAG, "onPageFinished");
                progressBar.setVisibility(View.GONE);
            }
            // 访问错误时回调,例如访问网页时报错404,在这个方法回调的时候可以加载错误页面。
            @Override
            public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
                super.onReceivedError(view, request, error);
                Log.e(TAG, "onReceivedError");
            }
        });
  • WebChromeClient

  • 主要辅助WebView处理Javascript的对话框、网站图标、网站title、加载进度等,有以下常用方法。
    • onJsAlert webview 不支持js的alert弹窗,需要自己监听然后通过dialog弹窗
    • onReceivedTitle 获取网页标题
    • onReceivedIcon 获取网页icon
    • onProgressChanged 加载进度回调
webView.setWebChromeClient(new WebChromeClient(){
            // alert弹窗如果不能弹出 需要创建一个WebChromeClient
            @Override
            public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
                AlertDialog.Builder localBuilder = new AlertDialog.Builder(webView.getContext());
                localBuilder.setMessage(message).setPositiveButton("确定",null);
                localBuilder.setCancelable(false);
                localBuilder.create().show();

                //注意:
                //必须要这一句代码:result.confirm()表示:
                //处理结果为确定状态同时唤醒WebCore线程
                //否则不能继续点击按钮
                result.confirm();
                return true;
//                return super.onJsAlert(view, url, message, result);
            }

            @Override
            public void onReceivedIcon(WebView view, Bitmap icon) {
                super.onReceivedIcon(view, icon);

            }

            @Override
            public void onReceivedTitle(WebView view, String title) {
                super.onReceivedTitle(view, title);
                Log.e(TAG, "onReceivedTitle = " + title);
            }

            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                super.onProgressChanged(view, newProgress);
                progressBar.setProgress(newProgress);
            }
        });
  • canGoBack和goBack

判断有没有上一页和返回上一页

@Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        // 点击返回按钮
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            // 判断有没有上一页
            if (webView.canGoBack()) {
                // 返回webView的上一个页面
                webView.goBack();
            } else {
                finish();
            }
        }
        return super.onKeyDown(keyCode, event);
    }

Android和JS相互调用

  • Android调用js方法

js代码

<script type="text/javascript">
		function showAlert(){
		  alert("欢迎调用js方法");
		}

		function addText(){
		  var x = document.getElementById("my_text");
		  x.innerHTML = "调用了js方法addText";
		}

	</script>

Android代码

webView.loadUrl("javascript:addText()");

其中addText()就是js中定义的方法,当android当前版本大于等于19时,可以使用最新方法调用

webView.evaluateJavascript("javascript:addText()", new ValueCallback<String>() {
                        @Override
                        public void onReceiveValue(String value) {
                            // 回调
                            Log.e(TAG, "onReceiveValue = " + value);
                        }
                    });

多了一个回调方法
两个方法的区别:通过loadUrl调用没有返回值且会刷新页面,但对版本没有要求,evaluateJavascript效果比较高有返回值且不会刷新页面,但需要4.4及以上才能使用,所以开发时需要配合使用

int version = Build.VERSION.SDK_INT;
                if (version < 19) {

                    webView.loadUrl("javascript:addText()");
                } else {
                    webView.evaluateJavascript("javascript:addText()", new ValueCallback<String>() {
                        @Override
                        public void onReceiveValue(String value) {
                            // 回调
                            Log.e(TAG, "onReceiveValue = " + value);
                        }
                    });
                }

这里需要注意的是 如果js方法里执行的是alert(),那么需要在android中设置

webSettings.setJavaScriptCanOpenWindowsAutomatically(true);// 设置允许JS弹窗
  • js调用Android方法

Android代码
1.直接定义方法

webView.addJavascriptInterface(this, "android");// js调用android方法
@JavascriptInterface
    public void showAndroid(){
        tv.setText("js调用了android方法");
    }

2.新建类

webView.addJavascriptInterface(new Myjs(), "test");// js调用android方法
public class Myjs{
        @JavascriptInterface
        public void showToast(){
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    tv.setText("js调用了android方法");
                }
            });

        }
    }

js代码

<input type="button" name="btn" value="js调用android" onclick="android.showAndroid()">

FAQ

  1. 为什么android调用js方法后,html不能弹窗
    答:是否使用了alert(),如果是,是否设置了
    webSettings.setJavaScriptEnabled(true);
    webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
    webView.setWebChromeClient(new WebChromeClient());

  2. 加载本地html文件不成功
    答:是否设置了webSettings.setAllowFileAccess(true);,是否开启了本地访问本地文件的读写权限,6.0以后需要动态申请

  3. 加载在线网页或者点击网页跳转时打开了android默认浏览器
    答:是否设置了webView.setWebViewClient(new WebViewClient());

  4. android调用js时多个参数如何传递
    答: webView.loadUrl("javascript:addText(" + "'" + param1+ "'" + "," + "'" + param2 + "'" + ")"); 需要将参数放到单引号中

参考

Android:你要的WebView与 JS 交互方式 都在这里了
Android WebView基本使用
Android:你不知道的 WebView 使用漏洞

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孤独的冥王星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值