Android_UI:WebView

WebView

根据url加载数据

相关的类:

  1. WebView
  2. WebViewClient:很多重写方法
  3. WebSettings:设置字体大小

Demo:

先显示进度条,当webview数据加载完成后,再把进度条隐藏。
注意加网络访问权限。

这里写图片描述

布局:activity_main.xml

<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"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/text_size"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:background="#3949AB"
        android:text="标题栏" 
        android:gravity="center"
        android:textSize="18sp"/>

    <WebView
        android:id="@+id/webView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/text_size" 
        android:visibility="gone"/>

    <ProgressBar
        android:id="@+id/progressBar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@+id/webView"
        android:layout_centerInParent="true" />

</RelativeLayout>

main.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android" >

    <item
        android:id="@+id/largest"
        android:orderInCategory="100"
        android:showAsAction="never"
        android:title="largest"/>
    <item
        android:id="@+id/larger"
        android:orderInCategory="99"
        android:showAsAction="never"
        android:title="larger"/>
    <item
        android:id="@+id/normal"
        android:orderInCategory="98"
        android:showAsAction="never"
        android:title="normal"/>
    <item
        android:id="@+id/smaller"
        android:orderInCategory="97"
        android:showAsAction="never"
        android:title="smaller"/>
    <item
        android:id="@+id/smallest"
        android:orderInCategory="96"
        android:showAsAction="never"
        android:title="smallest"/>

</menu>

代码:MainActivity.java

package com.cqc.webviewdemo01;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.webkit.WebSettings;
import android.webkit.WebSettings.TextSize;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.ProgressBar;

/**
 * WebView
 * 
 * @author cui 先显示进度条,webview加载完成后再显示webview,同时进度条消失
 */
public class MainActivity extends Activity {

    private WebView webView;
    private ProgressBar progressBar;
    private WebSettings settings;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);

        webView = (WebView) findViewById(R.id.webView);
        progressBar = (ProgressBar) findViewById(R.id.progressBar);

        String url = "http://news.qq.com/a/20160819/006774.htm";
        webView.loadUrl(url);
        webView.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                // 页面加载完成,就让进度条消失。
                progressBar.setVisibility(View.GONE);
                webView.setVisibility(View.VISIBLE);
            }
        });

        // 通过menu改变字体大小
        settings = webView.getSettings();
    }


    @Override
    protected void onPause() {
        super.onPause();
        webView.onPause();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return super.onCreateOptionsMenu(menu);
    }

    // 通过menu改变字体大小
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.largest:
            settings.setTextSize(TextSize.LARGEST);
            break;
        case R.id.larger:
            settings.setTextSize(TextSize.LARGER);
            break;
        case R.id.normal:
            settings.setTextSize(TextSize.NORMAL);
            break;
        case R.id.smaller:
            settings.setTextSize(TextSize.SMALLER);
            break;
        case R.id.smallest:
            settings.setTextSize(TextSize.SMALLEST);
            break;
        default:
            break;
        }
        return super.onOptionsItemSelected(item);
    }
}

点击下载源码

WebView详细使用

参考:
WebView详解与简单实现Android与H5互调
WebView小结

常用方法

loadUrl (String url)
setWebViewClient (WebViewClient client)

需要联网权限 ##

<uses-permission android:name="android.permission.INTERNET"/>

不加次权限会报错

setWebViewClient(…)

不使用该方法,那么点击超链接会让我们选择使用哪个浏览器。

webView.setWebViewClient(new WebViewClient());

使用该方法后,点击超链接直接在webView中跳转。

loadUrl (String url)

String url = "http://www.jikedaohang.com/";
webView.loadUrl(url);
或者
webView.loadUrl("file:///android_asset/Hello.html");

注意:一:file:后面是3个/;二:还android_asset,而不是assets。assets文件夹在main文件夹下。

WebViewClient中的几种方法

实现对网页中超链接的拦截(比如如果是极客导航的主页,则直接拦截转到百度主页):

2个方法,第一个过时了

shouldOverrideUrlLoading(WebView view, String url) 
shouldOverrideUrlLoading(WebView view, WebResourceRequest request)

先说第一个

shouldOverrideUrlLoading(WebView view, String url) 

点击按钮后,会先调用这个方法,所以我们可以重写这个方法拦截跳转。

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//  return super.shouldOverrideUrlLoading(view, url);//默认false
    if(url.contains("baidu")){
        view.loadUrl("http://www.csdn.net/");
    }
    return true;//true:web不在处理该事件,不加载url,不会打开新的界面
}

那么return true;与return false 有什么区别?
return super.shouldOverrideUrlLoading(view, url)默认值是false。
true:webView不处理该点击事件,也就是点击超连接不会调转界面。
false:webView处理该事件,会调转界面。

但是如果我们在return true;前又再次使用webView.loadUrl("http://www.jianshu.com/");方法,那么return truereturn false就没有区别了。
像下面这种,即使return true;也会调转打开超连接。

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
    if(url.contains("baidu")){
        webView.loadUrl("http://www.jianshu.com/");
    }
    return true;
}

默认false

return super.shouldOverrideUrlLoading(view, url);

另一个方法:

shouldOverrideUrlLoading(WebView view, WebResourceRequest request)
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
    if(request.getUrl().toString().contains("baidu")){
        webView.loadUrl("http://www.jianshu.com/");
    }
    return true;
}

默认false

return super.shouldOverrideUrlLoading(view, request);

该方法起不到拦截超连接的作用,返回true/false没有区别。
与上个方法不同的是,用WebResourceRequest代替了String url,request有更多的方法,只是需要在API>=21中使用

Uri url = request.getUrl();
String method = request.getMethod();
Map<String, String> requestHeaders = request.getRequestHeaders();

Uri转String

url.toString();

加载网页时替换某个资源(比如在加载一个网页时,需要加载一个logo图片,而我们想要替换这个logo图片,用我们assets目录下的一张图片替代)

第一个方法已过时

shouldInterceptRequest(WebView view, String url)
shouldInterceptRequest(WebView view, WebResourceRequest request) 

已过时的方法

@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
    WebResourceResponse response = null;
    if (url.contains("jk.png")) {
        try {
            InputStream is = getAssets().open("baidu.png");
            response = new WebResourceResponse("image/png", "UTF-8", is);
            LogUtil.d(TAG, "if");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return response;
}

默认返回null;

return super.shouldInterceptRequest(view, url);

未过时的方法:

shouldInterceptRequest(WebView view, WebResourceRequest request) 

同样也可以替换图片资源。

@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
    String path = request.getUrl().getPath();//相对路径 path=/jk.png,
    String url = request.getUrl().toString();//s=http://www.jikedaohang.com/jk.png
    WebResourceResponse response = null;
    if (url.contains("jk.png")) {
        try {
            InputStream is = getAssets().open("baidu.png");
            response = new WebResourceResponse("image/png", "UTF-8", is);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return response;
}
String path = request.getUrl().getPath();//相对路径 path=/jk.png,
String url = request.getUrl().toString();//url=http://www.jikedaohang.com/jk.png
LogUtil.d(TAG, "path=" + path + ",url=" + url);//path=/,s=http://www.jikedaohang.com/

设置开始加载网页、加载完成、加载错误时处理

@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
    LogUtil.d(TAG, "onPageStarted,ur=" + url);
    super.onPageStarted(view, url, favicon);
}

@Override
public void onPageFinished(WebView view, String url) {
    LogUtil.d(TAG, "onPageFinished,ur=" + url);
    progressBar.setVisibility(View.GONE);
    webView.setVisibility(View.VISIBLE);
    //super.onPageFinished(view, url);
   // if (!webView.getSettings().getLoadsImagesAutomatically()) {
     //   webView.getSettings().setLoadsImagesAutomatically(true);
   // }
}

@Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
    LogUtil.d(TAG, "onReceivedError,ur=" + request.getUrl().toString());
    progressBar.setVisibility(View.GONE);
    tv_error.setVisibility(View.VISIBLE);
    super.onReceivedError(view, request, error);
}

处理https请求,为WebView处理ssl证书设置WebView默认是不处理https请求的,需要在WebViewClient子类中重写父类的onReceivedSslError函数

/**处理https请求*/
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
    super.onReceivedSslError(view, handler, error);
//            handler.cancel();//默认,取消
//            handler.proceed();//处理
//            handler.handleMessage(null);//处理其它
}

WebChromeClient

private WebChromeClient chromeClient = new WebChromeClient() {
    @Override
    public void onProgressChanged(WebView view, int newProgress) {
        super.onProgressChanged(view, newProgress);
        setTitle("页面加载中..." + newProgress + "%");//ActionBar显示
        setProgress(newProgress * 100);//No longer supported starting in API 21.
    }
};

goBack()

点击返回键后,页面就消失了,退出了WebView,那么怎样实现向浏览器那样,退回到上一页?
这就重写onKeyDown(…)方法

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK && webView.canGoBack()) {
        webView.goBack();
        return true;
    }
    return super.onKeyDown(keyCode, event);
}

WebSettings配置

获取WebSettings对象

        WebSettings webSettings = webView.getSettings();

常用设置方法

(1)支持js

    settings.setJavaScriptEnabled(true);

(2)设置缓存方式,主要有以下几种:
LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据。
LOAD_DEFAULT: 根据cache-control决定是否从网络上取数据。
LOAD_CACHE_NORMAL: API level 17中已经废弃, 从API level 11开始作用同LOAD_DEFAULT模式。
LOAD_NO_CACHE: 不使用缓存,只从网络获取数据。
LOAD_CACHE_ELSE_NETWORK:只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。

    settings.setCacheMode(WebSettings.LOAD_NO_CACHE);

(3)开启DOM storage API功能(HTML5 提供的一种标准的接口,主要将键值对存储在本地,在页面加载完毕后可以通过 JavaScript 来操作这些数据。)

    settings.setDomStorageEnabled(true);

(4)设置数据库缓存路径

    settings.setDatabasePath(cacheDirPath);

(5)设置Application Caches缓存目录

    settings.setAppCachePath(cacheDirPath);

(6)设置默认编码

    settings.setDefaultTextEncodingName(“utf-8”);

(7)将图片调整到适合webview的大小

    settings.setUseWideViewPort(false);

(8)支持缩放

    settings.setSupportZoom(true);

(9)支持内容重新布局

    settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);

(10)多窗口

    settings.supportMultipleWindows();

(11)设置可以访问文件

    settings.setAllowFileAccess(true);

(12)当webview调用requestFocus时为webview设置节点

    settings.setNeedInitialFocus(true);

(13)设置支持缩放

    settings.setBuiltInZoomControls(true);

(14)支持通过JS打开新窗口

    settings.setJavaScriptCanOpenWindowsAutomatically(true);

(15)缩放至屏幕的大小

    settings.setLoadWithOverviewMode(true);

(16)支持自动加载图片

    settings.setLoadsImagesAutomatically(true);

三丶WebViewClient 的回调方法列表

WebViewClient主要用来辅助WebView处理各种通知、请求等事件,通过setWebViewClient方法设置。

(1)更新历史记录

    doUpdateVisitedHistory(WebView view, String url, boolean isReload)

(2)应用程序重新请求网页数据

   onFormResubmission(WebView view, Message dontResend, Message resend)

(3)在加载页面资源时会调用,每一个资源(比如图片)的加载都会调用一次。

    onLoadResource(WebView view, String url)

(4)开始载入页面调用,通常我们可以在这设定一个loading的页面,告诉用户程序在等待网络响应。

    onPageStarted(WebView view, String url, Bitmap favicon)

(5)在页面加载结束时调用。同样道理,我们知道一个页面载入完成,于是我们可以关闭loading 条,切换程序动作。

onPageFinished(WebView view, String url)

(6)报告错误信息

    onReceivedError(WebView view, int errorCode, String description, String failingUrl)

(7)获取返回信息授权请求

    onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host,String realm)

(8)重写此方法可以让webview处理https请求。

    onReceivedSslError(WebView view, SslErrorHandler handler, SslError error)

(9)WebView发生改变时调用

    onScaleChanged(WebView view, float oldScale, float newScale)

(10)Key事件未被加载时调用

    onUnhandledKeyEvent(WebView view, KeyEvent event)

(11)重写此方法才能够处理在浏览器中的按键事件。

    shouldOverrideKeyEvent(WebView view, KeyEvent event)

(12)在网页跳转时调用,这个函数我们可以做很多操作,比如我们读取到某些特殊的URL,于是就可以不打开地址,取消这个操作,进行预先定义的其他操作,这对一个程序是非常必要的。

    shouldOverrideUrlLoading(WebView view, String url)

(13)在加载某个网页的资源的时候多次调用(已过时)

    shouldInterceptRequest(WebView view, String url)

(14)在加载某个网页的资源的时候多次调用

    shouldInterceptRequest(WebView view, WebResourceRequest request)

注意:

shouldOverrideUrlLoading在网页跳转的时候调用,且一般每跳转一次只调用一次。
shouldInterceptRequest只要是网页加载的过程中均会调用,资源加载的时候都会回调该方法,会多次调用。

四丶WebChoromeClient的回调方法列表

WebChromeClient主要用来辅助WebView处理Javascript的对话框、网站图标、网站标题以及网页加载进度等。通过WebView的setWebChromeClient()方法设置。

(1)监听网页加载进度

    onProgressChanged(WebView view, int newProgress)

(2)监听网页标题 : 比如百度页面的标题是“百度一下,你就知道”

    onReceivedTitle(WebView view, String title)

(3)监听网页图标

    onReceivedIcon(WebView view, Bitmap icon)

Java和JavaScript的互调

在互相调用之前,先要webView支持js+是值缓存模式+加载url,这里一本地的html为例。

WebSettings settings = webView.getSettings();
settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
settings.setJavaScriptEnabled(true);
webView.loadUrl("file:///android_asset/Hello.html");

WebView添加支持JavaScript后,会报黄色警告

Using setJavaScriptEnabled can introduce XSS vulnerabilities into you application, review carefully

在方法声明上添加下方代码即可。

@SuppressLint("SetJavaScriptEnabled")

java调用js

JS中的方法:

<script type="text/javascript">
        function javaCallJs(text){
            document.getElementById("div1").innerHTML=text;
        }
</script>

java

webView.loadUrl("javascript:javaCallJs(" + "'" + "测试数据" + "'" + ")");

格式:

loadUrl("javascript:javaCallJs("+"'"+arg+"'"+")");

javascript:javaCallJs('str')
javascript:js中的方法名称(参数)

js调用java

java中的方法

webView.addJavascriptInterface(new MyJavaInterface(), "MyJavaInterface");

private class MyJavaInterface {
    @JavascriptInterface
    public void showToast(String text) {
        Toast.makeText(MainActivity.this, text, Toast.LENGTH_SHORT).show();
    }

    @JavascriptInterface
    public void setText(String text) {
        tv_content.setText(text);
    }
}

js

window.MyJavaInterface.showToast中的MyJavaInterface就是在java类中设置的参数webView.addJavascriptInterface(new MyJavaInterface(), “MyJavaInterface”);

<input type="button" value="js调用java中的方法" onclick="window.MyJavaInterface.showToast('弹出toast');">
<input type="button" value="js调用java中的方法:改变TextView的text" onclick="window.MyJavaInterface.setText('你好,中国!');">
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值