您的位置:首页 > 移动开发

WebView详解(一)

2016-08-19 11:36 387 查看

代码示例地址

前言

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。

@Override
public 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一样了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  webkit webview android