WebView最基本的使用

WebView

sky-mxc 总结 转载注明:https://sky-mxc.github.io

Android内置webkit内核的高性能浏览器,而WebView则是在这个基础上进行封装后的一个 控件,WebView直译网页视图,我们可以简单的看作一个可以嵌套到界面上的一个浏览器控件!
在 版本之后内核换成了 chrome 内核,但是 对外的API并没有更换

相关的类和方法

WebChromeClient

主要处理 对话框,网站title,icon 加载进度 等;侧重于对 内容的处理

方法 作用
onJsAlert(WebView view,String url,String message,JsResult result) 对js中alert对话框的处理
onJsConfirm(WebView view,String url,String message,JsResult result) 对js中confirm对话框的处理
onJsPrompt(WebView view,String url,String message,String defaultValue,JsPromptResult result) 对js中 Prompt对话框的处理
onProgressChanged(WebView view,int newProgress) 当加载进度发生变化时调用
onReceivedIcon(WebView view, Bitmap icon) 获得网页的icon
onReceivedTitle(WebView view,String title) 获取网页的标题

注意点: 在对话框处理完之后要对网页做出回应确认处理完成(result.confirm();)不让网页就会卡在 对话框那个地方 ,无法再次进行相应

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
private WebChromeClient chromeClient = new WebChromeClient(){
//网页加载进度显示
@Override
public void onProgressChanged(WebView view, int newProgress) {
Log.i(TAG, "onProgressChanged: progress="+newProgress);
if (newProgress!=100){
pb.setVisibility(View.VISIBLE);
pb.setProgress(newProgress);
}else{
pb.setVisibility(View.GONE);
}
}
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
Toast.makeText(MainActivity.this, message, Toast.LENGTH_SHORT).show();
//确认交互完成 提交结果 勿忘
result.confirm();
return true;
}
};

WebViewClient

主要处理WebView的各种请求通知; 侧重于对浏览器本身事件重写

方法 作用
onPageStared(WebView view,String url) 通知主程序网页开始加载
onPageFinished(WebView view,String url,Bitmap favicon) 通知主程序网页加载完毕
doUpdateVisitedHistory(WebView view,String url,boolean isReload) 更新历史记录
onLoadResource(WebView view,String url) 通知主程序即将加载指定url的资源
onScaleChanged(WebView view,float oldScale,float newScale) WebView的缩放改变时调用
shouldOverrideKeyEvent(WebView view,KeyEvent event) 控制WebView是否处理按键事件,如果返回true则处理,返回false则不处理
shouldOverrideUrlLoading(WebView view,String url) 控制对新加载的url的处理;例如在本view打开,返回true说明 处理 ,返回false说明不处理;
onReceivedError(WebView view,int errorCode,String description,String failingUrl) 遇到不可恢复的错误信息时调用

注意点:
shouldOverrideUrlLoading(WebView view,String url) 在 API 21中过时; 替代方法为shouldOverrideUrlLoading(WebView view, WebResourceRequest request)

1
2
3
4
5
6
7
8
9
10
11
//主要处理WebView的各种请求通知 侧重于 对 浏览器本身事件重写
private WebViewClient viewClient = new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Log.i(TAG, "shouldOverrideUrlLoading: url="+url);
//当打开一个新的 url 时在本view打开,不跳转至浏览器
view.loadUrl(url);
return true;
}
};

WebSettings

WebView相关配置的设置,比如setJavaScriptEnabled()设置是否允许JS脚本执行 部分方法如下:

方法 作用
setUseWideViewPort(boolean enabled) 是否支持viewPort
setLoadWithOverviewMode(boolean enabled) 自适应屏幕
setSupportZoom(boolean enabled) 是否支持缩放
setBuiltInZoomControls(boolean enabled) 目前没测试
setDisplayZoomControls(boolean enabled) 是否支持缩放控件
setDefaultFontSize(int size) 设置默认字体大小
setDefaultTextEncodingName(String encoding) 默认字符编码可用来解决中文乱码问题
setJavaScriptEnabled(boolean enabled) 是否支持js交互
1
2
3
4
5
6
7
//支持js交互
webView.getSettings().setJavaScriptEnabled(true);
//设置默认编码方式
webView.getSettings().setDefaultTextEncodingName("utf-8");
webView.getSettings().setDefaultFontSize(20);

WebView 自身的常用方法

方法 作用
loadUrl(String url) 加载指定的url
loadData(String data,String mimeType,String encoding) 加载指定的Data到WebView中.使用”data:”作为标记头,该方法不能加载网络数据.其中mimeType为数据类型如:textml,image/jpeg. encoding为字符的编码方式
loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl) loadData的升级版 可以以baseUrl为标准路径加载相应的文件等
getSettings() 返回一个WebSettings对象,用来控制WebView的属性设置
setWebViewClient(WebViewClient client) 为WebView指定一个WebViewClient对象
setWebChromeClient(WebChromeClient client) 为WebView制定一个 WebChromeClient对象
setBackgroundColor(int color) 设置WebView的背景颜色
setOnScrollChangeListener(View.OnScrollChangeListener changeListener) 滚动条滚动监听,在API 23 加入

注意点: WebView 背景色 需要代码进行设置 ;xml属性不好使;

加载指定的Url loadUrl();

1
2
//url
webView.loadUrl("http://baidu.com");

加载网页代码 loadData();如果出现中文乱码问题 需要修改 mimeType 为text/html;charset=utf-8

1
2
//加载网页代码
webView.loadData("<h1>title</h1>","text/html","utf-8");

基于一个url加载代码 loadDataWithBaseURL()不需要考虑中文乱码问题

1
2
3
4
5
6
7
//加载 以url为基准的数据 比loadData 更加强大
//parameter1 :代码内容中相对地址的基准路径
//parameter2 :网页代码
//parameter3 :数据的内容类型
//parameter4 : 编码
//parameter5 :上一个页面地址
webView.loadDataWithBaseURL("http://www.baidu.com","<html><h1>title</h1>this is content</html>","text/html","utf-8",null);

实例

加载 assets 目录下网页

  • 目录结构

    目录结构

  • html 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    <html>
    <head>
    <link type="text/css" rel="stylesheet" href="css/index.css"/>
    <script type="text/javascript" src="js/index.js"></script>
    </head>
    <body>
    <table class="table">
    <tr>
    <td>编号</td>
    <td>名称</td>
    <td>价格</td>
    <td>操作</td>
    </tr>
    <tr>
    <td>0</td>
    <td>节操</td>
    <td>0</td>
    <td onclick="del(this)">删除</td>
    </tr>
    <tr>
    <td>1</td>
    <td>贞操</td>
    <td>0</td>
    <td onclick="del(this)">删除</td>
    </tr>
    </table>
    </body>
    </html>
  • css

    1
    2
    3
    table{
    border:double 2px #ccc ;
    }
  • js

    1
    2
    3
    4
    function del(delBt){
    var result = confirm("确定删除吗?");
    alert("===="+result);
    }
  • 加载html文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    /**
    * 加载 assets目录下文件
    * @return
    */
    public String getIndex() {
    InputStream is =null;
    BufferedReader reader = null;
    try {
    is = getAssets().open("index.html");
    reader = new BufferedReader(new InputStreamReader(is));
    StringBuffer sb = new StringBuffer();
    while (reader.ready()){
    sb.append(reader.readLine().trim());
    }
    Log.i(TAG, "getIndex: html="+sb.toString());
    return sb.toString();
    } catch (IOException e) {
    e.printStackTrace();
    }finally {
    try {
    if (is!=null){
    is.close();
    }
    if (reader!=null){
    reader.close();
    }
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    return "";
    }
  • loadDataWithBaseURL加载html网页

    因为使用外部样式 需要使用 loadDataWithBaseUrl() 因为这个可以使用相对基准路径 可以将assets目录作为 基准目录;html 根据基准目录加载响应的css

1
2
String data = getIndex();
webView.loadDataWithBaseURL("file:///android_asset/",data,"text/html","utf-8",null);
注意点:
     路径的格式  :file:///android_asset/
  • 开启 js交互

    1
    2
    3
    4
    //支持js交互
    webView.getSettings().setJavaScriptEnabled(true);
    //背景色
    webView.setBackgroundColor(Color.GRAY);
  • 效果

    可以看到 css文件 加载到了 边框已经显示出来了

    效果;

    原始的 网页confirm 确认框

    效果;

    处理原始网页confirm 改为 AlertDialog对话框

    //处理JavaScript confirm 对话框
    @Override
    public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {
        new AlertDialog.Builder(MainActivity.this)
            .setTitle("确认提示")
            .setMessage(message)
            .setNegativeButton("Ok", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    result.confirm();
                }
            })
            .setNeutralButton("cancel", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    result.cancel();
                }
            })
            .show();
        return true;
    }
    

    效果;

    对 alert 对话框进行处理 改为 Toast显示

                @Override
    public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
        Toast.makeText(MainActivity.this, message, Toast.LENGTH_SHORT).show();
        //确认交互完成 提交结果 勿忘
        result.confirm();
        return true;
    }
    

效果;

获取网站的 title ico信息

重写 WebChromeClient内部方法

1
2
3
4
5
6
7
8
9
10
11
12
chromeClient = new WebChromeClient(){
//获取 title
@Override
public void onReceivedTitle(WebView view, String title){
tvTitle.setText(title);
}
//获取 icon
@Override
public void onReceivedIcon(WebView view, Bitmap icon) {
ImgIcon.setImageBitmap(icon);
}
};

效果;

WebView 的滚动监听

在API 23 加入了滚动监听的 get/set方法 ;
在API 23之前需要重写 WebView的 protected void onScrollChanged(final int l, final int t, final int oldl,final int oldt){}然后再对外提供一个接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//滚动条监听
webView.setOnScrollChangeListener(new View.OnScrollChangeListener() {
@Override
public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
// Log.e(TAG, "onScrollChange: scrollX="+scrollX);
// Log.e(TAG, "onScrollChange: oldScrollX="+oldScrollX);
Log.e(TAG, "onScrollChange: scrollY="+scrollY);
// Log.e(TAG, "onScrollChange: oldScrollY="+oldScrollY);
if (scrollY>0){
floatButton.setVisibility(View.VISIBLE);
}else{
floatButton.setVisibility(View.GONE);
}
dy = scrollX;
}
});

关于滚动条的设置

1
2
3
webView.setHorizontalScrollBarEnabled(false); //水平滚动条不显示
webView.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY); //WebView内部显示

回到顶部 实现 使用 方法 scrollTo(x,y);

1
2
3
4
5
6
7
8
floatButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i(TAG, "onClick: dy="+dy);
webView.scrollTo(0,0);
floatButton.setVisibility(View.GONE);
}
});

网页自适应

必须两个都写上, 缺一不可

1
2
settings.setUseWideViewPort(true); //支持 viewport
settings.setLoadWithOverviewMode(true); //自适应屏幕

效果;
效果;

支持缩放网页隐蔽缩放控件

1
2
3
4
//保留缩放功能 隐藏缩放控件
settings.setBuiltInZoomControls(true);
settings.setDisplayZoomControls(false);
settings.setSupportZoom(true); //支持缩放

回退键实现 返回网页回退 而不退出程序

重写 onBackPressed() 通过 canGoBack()判断是否能够回退 ,通过 goBack()实现回退

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Override
public void onBackPressed() {
//判断 WebView 是否可以回退
if (webView.canGoBack()){
webView.goBack();
}else{
Log.e(TAG, "onBackPressed: currentTimeMillis="+System.currentTimeMillis());
Log.e(TAG, "onBackPressed: exit="+exit);
Log.e(TAG, "onBackPressed: currentTimeMillis- exit="+(System.currentTimeMillis()-exit));
if (System.currentTimeMillis()-exit >2000){
Toast.makeText(this, "再按一次退出", Toast.LENGTH_SHORT).show();
exit= System.currentTimeMillis();
}else{
super.onBackPressed();
}
}
}

与js交互 js调用本地API

调用js function

未完待续。。。。

参考文章: http://www.runoob.com/w3cnote/android-tutorial-webview.html

坚持原创技术分享,您的支持将鼓励我继续创作!