前言
新的一天,新的文章,各位花粉肯定已经准备好学习新的知识了,那么今天依旧为大家带来一个实际项目中也非常实用的控件。现在市面上的 App
里几乎都内置了 Web
网页,比如说很多电商平台,某东、某宝等等,网页具有更新及时、部署方便等特点,移动端往往会搭配 WebView
去加载 H5
等页面。那么 WebView
究竟是何方神圣呢?Android
的 Webview
在低版本和高版本采用了不同的 webkit
版本内核,4.4后使用了 Chrome
内核,而 WebView
可以对 url
请求、页面加载、渲染、页面交互进行处理。
简介
WebView
代码语言:javascript复制java.lang.Object
↳android.view.View
↳android.view.ViewGroup
↳android.widget.AbsoluteLayout
↳android.webkit.WebView
其继承关系如上图所示,下面是一个简单的代码示例:
代码语言:javascript复制//WebView类下面的方法,通常使用的就是我们用来加载Url
mWebView.loadUrl("http://www.baidu.com");
//也可以配置请求头参数
Map<String, String> headers = new HashMap<>();
headers.put("token", "1234");
mWebView.loadUrl("http://www.baidu.com", headers);
//同样的也可以加载一段Html代码
mWebView.loadData("这里替换成你的html代码", "text/html; charset=UTF-8", null);
这里还有很多 WebView
的用法,在实际项目中会碰到很多场景应用到以下方法,所以各位花粉一定要了解,我们将每个方法都非常清晰的描述了一哈,希望可以给已经在开发的新花粉提供帮助:
WebSettings
通常我们需要给默认的 WebView
增加一些设置,比如支持缩放, JS
交互等属性,这里就要用到 WebSettings
,先初始化设置,再给大家讲解一下方法的作用:
//声明WebSettings子类
WebSettings ws = mWebView.getSettings();
//页面中与Javascript交互
webSettings.setJavaScriptEnabled(true);
//设置自适应屏幕,两者合用
//将图片调整到适合webview的大小
ws.setUseWideViewPort(true);
// 缩放至屏幕的大小
ws.setLoadWithOverviewMode(true);
//设置缩放
//设置缩放,默认为true,是setBuiltInZoomControls的前提
ws.setSupportZoom(true);
//设置内置的缩放控件。true则可以缩放
ws.setBuiltInZoomControls(true);
//隐藏缩放控件(类似放大镜的图标)
ws.setDisplayZoomControls(false);
//关闭webview中缓存
ws.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
//设置可以访问文件
ws.setAllowFileAccess(true);
//支持通过JS打开新窗口
ws.setJavaScriptCanOpenWindowsAutomatically(true);
//支持自动加载图片
ws.setLoadsImagesAutomatically(true);
//设置编码格式
ws.setDefaultTextEncodingName("utf-8");
//设置默认的字体大小,默认16,可取值1到72
ws.setDefaultFontSize(36);
/*
*API21调用
*当一个安全的来源(origin)试图从一个不安全的来源加载资源时配置WebView的行为。KITKAT以及之前的
*版本默认值为MIXED_CONTENT_ALWAYS_ALLOW,LOLLIPOP版本默认值MIXED_CONTENT_NEVER_ALLOW,WebView
*首选的最安全的操作模式为MIXED_CONTENT_NEVER_ALLOW ,不鼓励使用MIXED_CONTENT_ALWAYS_ALLOW。
*/
ws.setMixedContentMode (WebSettings.MIXED_CONTENT_ALWAYS_ALLOW)
/**
* LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据
* LOAD_DEFAULT: (默认)根据cache-control决定是否从网络上取数据。
* LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.
* LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据
*/
ws.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
//设置应用缓存文件的路径,为了让应用缓存API可用,此方法必须传入一个应用可写的路径。该方法只会执行一次
//重复调用会被忽略
ws.setAppCachePath(path);
/**
*设置应用缓存内容的最大值。所传值会被近似为数据库支持的最近似值,因此这是一个指示值,而不是一个固定值。
*所传值若小于数据库大小不会让数据库调整大小。默认值是MAX_VALUE,建议将默认值设置为最大值。
*/
ws.setAppCacheMaxSize();
WebViewClient
如果页面中链接,如果希望点击链接继续在当前应用中响应,而不是新开Android的系统浏览器中响应该链接,必须覆盖 WebView
的 WebViewClient
对象
mWebView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
});
除此之外,还有其他的可重写的方法我们来看一看
代码语言:javascript复制mWebView.setWebViewClient(new WebViewClient() {
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
//可以在这里显示loading加载等业务
}
@Override
public void onPageFinished(WebView view, String url) {
//可以关闭loading加载等业务
}
@Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
//加载页面的服务器出现错误时调用 error.getErrorCode()对应异常码,可以进行业务处理
}
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
//默认是不处理https请求的页面显示空白,尤其在加载的url域名配置https后,常见的是url中的图片看不见了,就是因为https的默认不处理导致,配置如下解决
handler.proceed();
}
});
WebChromeClient
代码语言:javascript复制mWebView.setWebChromeClient(new WebChromeClient(){
@Override
public void onProgressChanged(WebView view, int newProgress) {
//监听加载进度,通常有进度条需要在这里设置进度
}
@Override
public void onReceivedTitle(WebView view, String title) {
//在此可以获取标题
}
});
实例演示
这里我们来演示一个带进度条的加载 url
的实例。
因为 WebView
需要加载网页需要网络访问权限,在你的 AndroidManifest.xml
中检查一下权限
<uses-permission android:name="android.permission.INTERNET"/>
增加一个 activity_webview.xml
布局如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<WebView
android:id="@ id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ProgressBar
android:id="@ id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="10dp" />
</RelativeLayout>
在 Activity
中编写代码如下:
/**
* WebView必知必会的基础
*
* @author xmkh
*/
public class WebViewActivity extends AppCompatActivity {
private WebView mWebView;
private ProgressBar mProgressbar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_webview);
mWebView = findViewById(R.id.webview);
mProgressbar = findViewById(R.id.progressBar);
mProgressbar.setMax(100);
//优先使用缓存:
WebSettings ws = mWebView.getSettings();
mWebView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
});
mWebView.setWebChromeClient(new WebChromeClient() {
@Override
public void onProgressChanged(WebView view, int newProgress) {
//监听加载进度,通常有进度条需要在这里设置进度
if (newProgress == 100) {
mProgressbar.setVisibility(View.GONE);
} else {
mProgressbar.setProgress(newProgress);
}
}
});
mWebView.loadUrl("http://www.baidu.com");
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
//点击返回上一页面,如果有多级页面历史,则回退到上一级而不是退出Activity
if (keyCode == KeyEvent.KEYCODE_BACK && mWebView.canGoBack()) {
mWebView.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
@Override
protected void onDestroy() {
//进来避免内存泄漏
if (mWebView != null) {
mWebView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
mWebView.clearHistory();
((ViewGroup) mWebView.getParent()).removeView(mWebView);
mWebView.destroy();
mWebView = null;
}
super.onDestroy();
}
}
大功告成,最终实现效果如下: