WebView详解(一)

来源:互联网 发布:北京学java最好的学校 编辑:程序博客网 时间:2024/06/06 13:22

代码示例地址

前言

WebView一直是安卓的一个大坑,新版本经常会废弃旧版本的api,导致在使用WevView的时候经常会遇到各种各样的问题,在此整理下WebView的用法及一些坑。

一、 WebView介绍

WebView(网络视图)能加载显示网页,可以将其视为一个浏览器。它使用了WebKit渲染引擎加载显示网页。iOS的UIWebView也同样使用的是WebKit内核,不知道为何渲染速度比Android快很多,坑也比Android少。
本章主要包含WebView的简单使用;WebView常用的三个类WebSettings,WebViewClient,WebChromeClient;进度条;在当前WebView中打开新连接,不跳转到系统浏览器;back键返回访问历史;js与原生互调;加载web url,插入本地js。

1、简单的使用

(1)在布局里声明WebView。

<WebView    android:id="@+id/mWebView"    android:layout_width="match_parent"    android:layout_height="match_parent" />        

(2)使用loadUrl方法加载网页。

mWebView = (WebView) findViewById(R.id.mWebView);mWebView.loadUrl("http://wujinkui.com/");

二、使用WebView常用到的三个类

1、WebSettings 关于WebView的一些设置,比如缓存,js等
2、WebViewClient 主要帮助WebView处理各种通知、请求事件等
3、WebChromeClient 主要辅助WebView处理Javascript的对话框、网站图标、网站title、加载进度等

1、WebSettings

获取WebSettings:WebSettings settings = mWebView.getSettings();

方法:

不是说所有的方法都列出来了,只是一些会用到的,下同

//下面三个最常用,基本都需要设置
setCacheMode 设置缓存的模式 eg: settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
setJavaSciptEnabled 设置是否支持Javascript eg: settings.setJavaScriptEnabled(true);
setDefaultTextEncodingName 设置在解码时使用的默认编码 eg: settings.setDefaultTextEncodingName(“utf-8”);
setAllowFileAccess 启用或禁止WebView访问文件数据
setBlockNetworkImage 是否显示网络图像
setBuiltInZoomControls 设置是否支持缩放
setDefaultFontSize 设置默认的字体大小
setFixedFontFamily 设置固定使用的字体
setLayoutAlgorithm 设置布局方式
setLightTouchEnabled 设置用鼠标激活被选项
setSupportZoom 设置是否支持变焦

2、WebViewClient

设置WebViewClient:mWebView.setWebViewClient(new WebViewClient());

方法:

onPageStarted 网页开始加载
onReceivedError 报告错误信息
onLoadResource 加载指定地址提供的资源
shouldOverrideUrlLoading 控制新的连接在当前WebView中打开
onPageFinished 网页加载完毕,此方法并没有方法名表现的那么美好,调用时机很不确定。如需监听网页加载完成可以使用onProgressChanged,当int progress返回100时表示网页加载完毕。
doUpdate VisitedHistory 更新历史记录
onFormResubmission 应用程序重新请求网页数据
onScaleChanged WebView发生改变

3、WebChromeClient mWebView.setWebViewClient(new WebChromeClient());

方法:

onProgressChanged 加载进度条改变
onJsPrompt 用在解决4.2以下addJavascriptInterface漏洞问题
onCloseWindow 关闭WebView
onCreateWindow 创建WebView
onJsAlert 处理Javascript中的Alert对话框
onJsConfirm处理Javascript中的Confirm对话框
onJsPrompt处理Javascript中的Prompt对话框
onReceivedlcon 网页图标更改
onReceivedTitle 网页Title更改
onRequestFocus WebView显示焦点
onConsoleMessage 在Logcat中输出javascript的日志信息

三、WebView复杂的使用

1、进度条

在WebChromeClient里有onProgressChanged方法,利用此方法可以实现进度条。

(1)布局

<RelativeLayout    android:layout_width="match_parent"    android:layout_height="match_parent">    <WebView        android:id="@+id/mWebView"        android:layout_width="match_parent"        android:layout_height="match_parent" />    <ProgressBar        android:id="@+id/mProgressBar"        style="?android:attr/progressBarStyleHorizontal"        android:layout_width="match_parent"        android:layout_height="3dp"        android:layout_gravity="center_vertical"        android:max="100"        android:progressDrawable="@drawable/progress_bar_web_view" /></RelativeLayout>

(2)重写onProgressChanged方法

mWebView.setWebChromeClient(new WebChromeClient() {    @Override    public void onProgressChanged(WebView view, int newProgress) {        if (newProgress == 100) {            // 网页加载完成            mProgressBar.setVisibility(View.GONE);        } else {            // 加载中            mProgressBar.setVisibility(View.VISIBLE);            mProgressBar.setProgress(newProgress);        }    }});

2、在当前WebView中打开新连接,不跳转到系统浏览器

重写WebViewClient的shouldOverrideUrlLoading方法

mWebView.setWebViewClient(new WebViewClient() {    @Override    public boolean shouldOverrideUrlLoading(WebView view, String url) {        if(你想在当前页面打开新连接){            view.loadUrl(url);        }else if(在一个新的activity中打开新连接){            Intent intent = new Intent(mContext, NewWebViewActivity.class);            intent.putputExtra("URL", url);            startActivity(intent);        }        return true;    }});

在Android N中 shouldOverrideUrlLoading(WebView view, String url)被废弃,改为shouldOverrideUrlLoading(WebView view, WebResourceRequest request),我们可以通过request.getUrl()来获取url。

@Overridepublic boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {    return shouldOverrideUrlLoading(view, request.getUrl().toString());}

3、back键返回访问历史

mWebView.setOnKeyListener(new View.OnKeyListener() {    @Override    public boolean onKey(View v, int keyCode, KeyEvent event) {        if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {            // 返回键退回            mWebView.goBack();            return true;        } else            return false;    }});

4、js与原生互调

原生调用js方法

准备工作,创建一个test.html文件,在此html中创建一个js方法alertMsg,作用为将java里传来的message弹出。

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html>    <head>        <meta http-equiv="Content-Type" content="text/xhtml; charset=utf-8"/>        <title ng-bind="title">原生与js互调</title>        <!-- 下面注释用来演示加载本地js文件 -->        <!--<script type="text/javascript" src="file:///android_asset/main.js"></script>-->        <script type="text/javascript">            function alertMsg(message) {                alert(message)            }        </script>    </head>    <body>        <p>HTML page load success!</p>        <!-- js调用原生的Buttion -->        <button type="button" onclick="window.stub.nativeMethod('来至JS的参数');">JS调用原生方法</button>    </body></html>

布局文件里写一个Button,点击此Butiton,调用js方法。

findViewById(R.id.btn_call_js_method).setOnClickListener(new View.OnClickListener() {    @Override    public void onClick(View view) {        //调用alertMsg方法,并传递参数"来自原生的字符串"。        mWebView.loadUrl("javascript:alertMsg('" + "来自原生的字符串" + "')");    }});

点击后页面显示对话框,内容为“来自原生的字符串”。

js调用原生方法
//stub、nativeMethod可自定义,但在java代码里和html代码里必须一致。mWebView.addJavascriptInterface(new JSCallback(), "stub"); //stub为window.stub.nativeMethod中的stub,为自定义.public class JSCallback {    //nativeMethod为window.stub.nativeMethod中的nativeMethod    @JavascriptInterface    public void nativeMethod(String data) {        Toast.makeText(NormalActivity.this, data, Toast.LENGTH_SHORT).show();    }}

5、加载web url,插入本地js

在assets文件夹新建一个alert.js。只有一个方法,接受一个mseesage,并将message弹出。

function aliert(message) {    alert(message)}

在onPageFinished方法回调的时候,将此js插入到WebView中。此处有坑,尝试了网上的各种方法,均不能成功,最后在stackoverflow上找到方法。

wvContent.setWebViewClient(new WebViewClient() {    @Override    public void onPageFinished(WebView view, String url) {        super.onPageFinished(view, url);        injectScriptFile(view, "alert.js");    }    //ref http://stackoverflow.com/questions/21552912/android-web-view-inject-local-javascript-file-to-remote-webpage    private void injectScriptFile(WebView view, String scriptFile) {        InputStream input;        try {            input = getAssets().open(scriptFile);            byte[] buffer = new byte[input.available()];            input.read(buffer);            input.close();            String encoded = Base64.encodeToString(buffer, Base64.NO_WRAP);            view.loadUrl("javascript:(function() {" +                    "var parent = document.getElementsByTagName('head').item(0);" +                    "var script = document.createElement('script');" +                    "script.type = 'text/javascript';" +                    // Tell the browser to BASE64-decode the string into your script !!!                    "script.innerHTML = window.atob('" + encoded + "');" +                    "parent.appendChild(script)" +                    "})()");        } catch (IOException e) {            e.printStackTrace();        }    }});

接下来就和用原生调用js一样了。

0 0
原创粉丝点击