原来你是这样的WebView

Posted SmallCheric

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了原来你是这样的WebView相关的知识,希望对你有一定的参考价值。

随着html5的快速发展,越来越多的App对WebView的使用越来越频繁,不再像以前一样只需要调用webview.loadurl(url)就可以满足基本的使用,本文就对目前WebView的常用用法进行总结介绍,希望能帮到一些小伙伴…

1. WebView是个什么鬼

一个用来展示web界面的View, WebView可以在自己的浏览器或者Activity中进行内容展示,采用了WebKit渲染引擎来显示网页,包括历史导航,前一页,后一页,放大,缩小,执行搜索文本等功能;如果你想在项目中使用WebView,需要添加一个访问网络的权限:

uses-permission android:name=”android.permission.INTERNET”

2. WebView的基本使用

2.1 发送Intent调用系统浏览器打开加载页

WebView在默认情况下,不支持浏览器中例如widget插件,默认关闭Js交互,并忽略网页上将被忽略;如果你只想展示一个页面,但是并不需要交互,那使用webview是比较合适的; 如果你想实现一个全面的web页面,那么你可以开启一个URL意图来使用浏览器打开当前URL,但一般为了用户体验,这种用法的使用还是比较少的;示例如下

Uri uri = Uri.parse("http://www.baidu.com");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);

2.2 调用webview.loadUrl(url)来加载

2.2.1 webview.loadUrl(url)加载网络地址

当然,多数情况下,我们会在layout文件中定义一个webview控件,然后在Activity中的onCreate里面加载我们想要看到的url界面,使用如下:

    //第一种写法,常用格式
    WebView webView = (WebView) findViewById(R.id.webview);
    webView.loadUrl("http://www.baidu.com");
    //注意:如果不想弹出系统浏览器进行界面显示,需要重写该方法
    webView.setWebViewClient(new WebViewClient()
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) 
            view.loadUrl(url);
            //返回值没有关系
            return super.shouldOverrideUrlLoading(view,url);
        
    );

    //第二种写法,直接在setContentView中传入webview
    WebView webView = new WebView(this);
    webView.loadUrl("http://www.baidu.com");
    setContentView(webView);
    webView.setWebViewClient(new WebViewClient()
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) 
            view.loadUrl(url);
            //返回值没有关系
            return super.shouldOverrideUrlLoading(view,url);
        
    );

注意:如果不想弹出系统浏览器进行界面显示,需要重写shouldOverrideUrlLoading方法

2.2.2 webview.loadUrl(url)加载apk包内html文件

webview不但可以加载网络页面,也可以加载apk包下的html文件,将html文件放在项目assets资源目录下,然后调用以下代码即可

webView.loadUrl("file:///android_asset/test.html");

2.2.3 webview.loadUrl(url)加载SD卡下的html文件

webview加载SD卡根目录下test.html文件代码如下:

webView.loadUrl("content://com.android.htmlfileprovider/sdcard/test.html");

2.3 webview加载HTML格式字符串

除了可以加载网页之外,webview也可以加载HTML格式的字符串;主要是两个方法,一个webView.loadData(data,mimeType,encoding);来展示,一个是webView.loadDataWithBaseURL(baseUrl,data,mimeType,encoding,historyUrl);. 如果是带有中文的数据,默认显示会展示乱码,可以有两种方式来解决乱码;我们先来看一下如果都是英文数据该如何展示:

String data = "<html><body>You scored <b>Egglish</b> points.</body></html>";
webView.loadData(summary, "text/html", null);

展示效果如图所示:

如果包含了中文,会显示乱码:

第一种修改方式,可以在loadData中更改第二个参数,注意:如果将第三个参数更改为”UTF-8”,依然会是乱码;正确修改如下:

String data = "<html><body>You scored <b>中文测试</b> points.</body></html>";
webView.loadData(data, "text/html; charset=UTF-8", null);

显示效果如下:

原因如下:

如果用 loadDataWithBaseURL时,如果不传入URL时,刷新会造成白屏,因为刷新时调用的的是reload方法,reload是根据传入的URL进行一次重新加载即再次loadUrl(url),不传入URL时,默认的的URL是about:blank;使用loadData,刷新只是从缓存里面取,但是在4.0以上的,如果按照API里所写的loadData(data, “UTF-8”, null);时会乱码,如果写成loadData(data, "text/html; charset=UTF-8", null);loadData最终的机制是会把传入的三个参数拼接在一起,然后再进行loadUrl操作,参数就是data, "text/html; charset=UTF-8", null这三个进行拼装,加入text/html; charset=UTF-8就相当于限定了页面的字符

上面的一种修改方式可以适配大多数机型,但依然有少部分机型会显示乱码,可能与系统底层文件修改有关,所以就有了另一种修改方式,调用loadDataWithBaseURL方法,修改如下:

String data = "<html><body>You scored <b>中文测试</b> points.</body></html>";
webView.loadDataWithBaseURL(null,summary,"text/html","UTF-8",null);

3. 自定义你的webview

WebView除了基本的用法以外,还可以进行自定义来达到你想要的效果,比如创建一个匿名WebChromeClient来辅助WebView处理javascript的对话框,网站图标,网站title,加载进度等;也可以创建一个匿名WebViewClient ,来帮助WebView处理各种通知、请求事件等;当然,也可以启用 WebSettings,来开启Js交互等等,下面我们就来逐一介绍.

3.1 WebChromeClient

方法中的代码均有Android端自行处理,实现方式可以写一个匿名内部类,或者写一个WebChromeClient类,然后调用webview.setWebChromeClient(mWebChromeClient);代码示例如下:

webView.setWebChromeClient(new WebChromeClient() 
    //获取网页的加载进度,因有的网页是采用分模块加载,所以进度值并非只是一次1~100;可以为: 29~100;30~100;
    @Override
    public void onProgressChanged(WebView view, int progress) 
        Log.e(TAG,"progress="+progress);
    

    //获取当前网页中的Title值来设置给自己的title
    //注意:如果无网,获取的 title= 找不到网页
    //所以开发者可以在接受到onReceiveError的回调后,不要在使用当前获取的title值了
    @Override
    public void onReceivedTitle(WebView view, String title) 
        Log.e(TAG,"title="+title);
    
    //获取当前网页的icon,拿到后,会获取一个Bitmap对象,你想干嘛就干嘛
    @Override
    public void onReceivedIcon(WebView view, Bitmap icon) 
        super.onReceivedIcon(view, icon);
    

);

以上为简单用法,下面我们对 onJsAlert(), onJsPrompt(),onJsConfirm()进行逐一分析;在WebChromeClient类里可以重写这三个方法,此时WebView中加载的html中如果执行alert("alert...."); , confirm("confirm..."); , prompt("prompt...", "defaultValue");这三个方法,该类就会监听到执行对应的三个方法。我们可以让这三个方法的返回值为true ,即自定义此方法。在里面写入自己定义的Dialog,便可实现html与Activity交互。

注意 JsResult 此类需要在操作时,如果操作则 result.cofirm(). 取消则 result.cancel(); 还必须这每一个方法中写入 dialog.setOnkeyListener(); 方法来监听Back键,listener中    要写 result.cancel(); 否则系统没有消费这个事件,会出错。

3.1.1 自定义onJsAlert

什么是Javascript Alert?

Alert是一种提示信息或者警告信息的对话框,一旦显示到用户面前,只能点击OK才能关闭.

通常一般的实现类似:

<html>
   <SCRIPT type="text/javascript">
       alert('This is alert dialog !')
   </SCRIPT>
</html>

效果图如下:

onJsAlert API 介绍:

public boolean onJsAlert (WebView view, String url, String message, JsResult result)

Tell the client to display a javascript alert dialog. If the client returns true, WebView will assume that the client will handle the dialog. If the client returns false, it will continue execution.

告知客户端将显示一个alert dialog; 如果方法返回了true, 那么webview就会来自行处理这个dialog; 如果返回了false,则会继续执行下去,webview不进行处理;

在Android中,我们一般重写onJsAlert方法,会将参数中的message信息用Toast的形式弹出以告知用户,代码如下;

@Override
   public boolean onJsAlert(WebView view, String url, String message, JsResult result) 
       Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
       因为没有绑定事件,需要强行confirm,否则页面会变黑显示不了内容。
       result.confirm();
       return true;
   

或者我们可以自行弹出一个Dialog,覆盖默认的显示界面,代码如下:

@Override
   public boolean onJsAlert(WebView view, String url, String message, JsResult result) 
       final AlertDialog.Builder builder = new AlertDialog.Builder(view
               .getContext());
       builder.setTitle("测试自定义对话框").setMessage(message)
               .setPositiveButton("确定", null);
       //这里不需要绑定按键事件
       //可自行屏蔽keycode按键
       builder.setOnKeyListener(new DialogInterface.OnKeyListener() 
           @Override
           public boolean onKey(DialogInterface dialog, int keyCode,
                                KeyEvent event) 
               Log.e(TAG,"keyCode==" + keyCode + "event=" + event);
               return true;
           
       );
       //禁止响应按back键的事件
       builder.setCancelable(false);
       AlertDialog dialog = builder.create();
       dialog.show();
       result.confirm();//因为没有绑定事件,需要强行confirm,否则页面会变黑显示不了内容。
       return true;
   

3.1.2 自定义onJsConfirm

用法与onJsAlert基本一样,直接上代码:

@Override
   public boolean onJsConfirm(WebView view, String url, String message,
                              final JsResult result) 
       final AlertDialog.Builder builder = new AlertDialog.Builder(view
               .getContext());
       builder.setTitle("webview测试confirm对话框")
               .setMessage(message)
               .setPositiveButton("确定", new DialogInterface.OnClickListener() 
                   @Override
                   public void onClick(DialogInterface dialog, int which) 
                       result.confirm();
                   
               )
               .setNeutralButton("取消", new DialogInterface.OnClickListener() 
                   @Override
                   public void onClick(DialogInterface dialog, int which) 
                       result.cancel();
                   
       );
       builder.setOnCancelListener(new DialogInterface.OnCancelListener() 
           @Override
           public void onCancel(DialogInterface dialog) 
               result.cancel();
           
       );

       //屏蔽keycode的按键,避免按键后导致对话框消息而页面无法再弹出对话框的问题
       builder.setOnKeyListener(new DialogInterface.OnKeyListener() 
           @Override
           public boolean onKey(DialogInterface dialog, int keyCode,
                                KeyEvent event) 
               Log.e(TAG, "keyCode==" + keyCode + "event=" + event);
               return true;
           
       );
       //禁止响应按back键的事件
       builder.setCancelable(false);
       AlertDialog dialog = builder.create();
       dialog.show();
       return true;
   

3.1.3 自定义 onJsPrompt

直接上代码,大致用法一样,只不过个别参数不同:

@Override
   public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, final JsPromptResult result) 
       final AlertDialog.Builder builder = new AlertDialog.Builder(view
               .getContext());
       builder.setTitle("webview测试prompt对话框").setMessage(message);

       final EditText et = new EditText(view.getContext());
       et.setSingleLine();
       et.setText(defaultValue);
       builder.setView(et);
       builder.setPositiveButton("确定", new DialogInterface.OnClickListener() 
           @Override
           public void onClick(DialogInterface dialog, int which) 
               result.confirm(et.getText().toString());
           
       ).setNeutralButton("取消", new DialogInterface.OnClickListener() 
           @Override
           public void onClick(DialogInterface dialog, int which) 
               result.cancel();
           
       );

       //屏蔽keycode按键,避免按键后导致对话框消息而页面无法再弹出对话框的问题
       builder.setOnKeyListener(new DialogInterface.OnKeyListener() 
           @Override
           public boolean onKey(DialogInterface dialog, int keyCode,
                                KeyEvent event) 
               Log.e(TAG, "keyCode==" + keyCode + "event=" + event);
               return true;
           
       );

       //禁止响应按back键的事件
       builder.setCancelable(false);
       AlertDialog dialog = builder.create();
       dialog.show();
       return true;
   

4. 使用websettings让你的webview更加强大

webview获取到websettings之后,可以对当前的webview进行各种设置,如 Js交互开启,缩放,支持插件等等,我们直接以代码为例,代码中对每个功能点都进行了详细说明,请小伙伴参阅;

WebSettings webSettings = webView.getSettings();

   //支持获取手势焦点,输入用户名、密码或其他
   webView.requestFocusFromTouch();
   //支持js交互
   webSettings.setJavaScriptEnabled(true);
   webSettings.setJavaScriptCanOpenWindowsAutomatically(true); //支持通过JS打开新窗口

   //设置自适应屏幕,需要与setLoadWithOverviewMode合用
   webSettings.setUseWideViewPort(true);  //可以将图片调整到适合webview的大小
   webSettings.setLoadWithOverviewMode(true); // 缩放至屏幕的大小

   //支持缩放,默认为true。是setBuiltInZoomControls的前提。
   //若setSupportZoom是false,则该WebView不可缩放,这个不管setBuiltInZoomControls设置什么都不能缩放。
   webSettings.setSupportZoom(true);
   webSettings.setBuiltInZoomControls(true); //设置内置的缩放控件

   webSettings.setDisplayZoomControls(false); //隐藏原生的缩放控件

   //提高渲染的优先级
   webSettings.setRenderPriority(WebSettings.RenderPriority.HIGH);

   webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN); //支持内容重新布局
   webSettings.supportMultipleWindows();  //支持多窗口
   webSettings.setAllowFileAccess(true);  //设置可以访问文件
   webSettings.setLoadsImagesAutomatically(true);  //支持自动加载图片
   webSettings.setDefaultTextEncodingName("utf-8");//设置编码格式

好了,上面就是webview的一些简单用法,后面我们将对webview的缓存机制,前进回退操作,与js互调,避免webview内存泄露等问题进行逐一分析,希望我的文字能在你需要的时候帮到你, 愿大家有美好的一天…..

以上是关于原来你是这样的WebView的主要内容,如果未能解决你的问题,请参考以下文章

原来你是这样的lua

微信小程序内嵌webview,部分安卓机型无法打开h5界面

Webview 活动在失去焦点时调用 onDestroy()

原来你是这样的setTimeout

原来你是这样的PaaS!

iOS 14 相机顶部增加按钮,原来是这样「进化」来的