android WebView全面详解

本文详细介绍了WebView的基本使用方法,包括加载本地和远程网页、与JavaScript交互等内容,并提供了代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自:http://www.itbbu.com/1472.html

WebView是安卓中用来显示html文本内容的的控件,对html5也有很好的支持,ios的控件UIWebView差不多。网上对WebView的解释很多,但都是零星的介绍,导致到现在为止webview给我的印象都是,貌似很强大,其实很鸡肋,于是决定总结一下webview的开发经验。

使用WebView并不需要开通网络权限

网上有文章说webview需要开通internet权限,否则会出Web page not available错误,这是不对的,出现Web page not available并不是因为使用了webview,而是webview访问了网络,如果webview只是加载本地html(比如assets目录中的文件),或者只是加载带有html文本的字符串,即使没有internet权限,也不会报错。

如何调用webview

xml中

1
2
3
4
5
<WebView
     android:id= "@+id/blog_detail_webview"
     android:layout_width= "fill_parent"
     android:layout_height= "wrap_content"
     android:background= "#FFFFFF" />

activity中

1
2
3
4
5
6
mWebView = (WebView)findViewById(R.id.blog_detail_webview);
mWebView.getSettings().setJavaScriptEnabled( false );
mWebView.getSettings().setSupportZoom( false );
mWebView.getSettings().setBuiltInZoomControls( false );
mWebView.getSettings().setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);
mWebView.getSettings().setDefaultFontSize(18);

基本设置

上面的java代码部分相信大家都懂,可以看到WebView 和其他控件不同的地方在于其属性设置是调用mWebView.getSettings()来完成的,不知道谷歌这样设计的用意,其中:

mWebView.getSettings().setJavaScriptEnabled(false);

表示不支持js,如果想让java和js交互或者本身希望js完成一定的功能请把false改为true。

mWebView.getSettings().setSupportZoom(false);

设置是否支持缩放,我这里为false,默认为true。

mWebView.getSettings().setBuiltInZoomControls(false);

设置是否显示缩放工具,默认为false。

mWebView.getSettings().setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);

一般很少会用到这个,用WebView组件显示普通网页时一般会出现横向滚动条,这样会导致页面查看起来非常不方便。LayoutAlgorithm是一个枚举,用来控制html的布局,总共有三种类型:
NORMAL:正常显示,没有渲染变化。
SINGLE_COLUMN:把所有内容放到WebView组件等宽的一列中。
NARROW_COLUMNS:可能的话,使所有列的宽度不超过屏幕宽度。

mWebView.getSettings().setDefaultFontSize(18);

设置默认的字体大小,默认为16,有效值区间在1-72之间。

加载内容

(1)加载assets目录下的本地网页

一般我们都是把html文件放在assets目录下, WebView调用assets目录下的本地网页和图片等资源非常方便,使用形如

1
mWebView.loadUrl( "file:///android_asset/html/test1.html" );

的调用方法即可。

(2)加载远程网页

1
mWebView.loadUrl( "http://www.google.com" );

(3)使用 LoadData 或者 loadDataWithBaseURL方法加载内容

有时候我们的webview可能只是html片段,而不是一个完整的网页,事实上绝大多数时候都是如此,完整的网页无需做成应用,而直接在浏览器访问。

这种情况我们使用 LoadData 或者 loadDataWithBaseURL方法,后者用的最多:

void loadDataWithBaseURL (String baseUrl, String data, String mimeType, String encoding, String historyUrl)

loadDataWithBaseURL()比loadData()多两个参数,可以指定HTML代码片段中相关资源的相对根路径,也可以指定历史Url,其余三个参数相同。

这里主要注意参数baseUrl,baseUrl指定了你的data参数中数据是以什么地址为基准的,因为data中的数据可能会有超链接或者是image元素,而很多网站的地址都是用的相对路径,如果没有baseUrl,webview将访问不到这些资源。

举个例子:

1
2
String body = "示例:这里有个img标签,地址是相对路径<img src='/uploads/allimg/130923/1FP02V7-0.png' />" ;
mWebView.loadDataWithBaseURL( "http://www.jcodecraeer.com" , body,  "text/html" "utf-8" , null );

如果baseUrl没有指定为http://www.jcodecraeer.com,那么这张图片将显示不出来。

上面的例子其实演示了loadDataWithBaseURL的用法,我们直接加载一个字符串里面的html内容,而有些时候这些内容是从assets目录下的本地网页文件中读取,下面我们将html/test1.html中的内容通过LoadData来加载:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
String data =  "" ;
try  {
     // 读取assets目录下的文件需要用到AssetManager对象的Open方法打开文件
     InputStream is = getAssets().open( "html/test2.html" );
     // loadData()方法需要的是一个字符串数据所以我们需要把文件转成字符串
     ByteArrayBuffer baf =  new  ByteArrayBuffer(500);
     int count = 0;
     while  ((count = is.read()) != -1) {
         baf.append(count);
     }
     data = EncodingUtils.getString(baf.toByteArray(),  "utf-8" );
catch  (IOException e) {
     e.printStackTrace();
}
// 下面两种方法都可以加载成功
mWebView.loadData(data,  "text/html" "utf-8" );
// wv.loadDataWithBaseURL("", data, "text/html", "utf-8", "");

这种通过读取文件再用loadData加载其实和mWebView.loadUrl("file:///android_asset/html/test1.html")

是一致的,只不过loadData方式因为没有指定地址的基准url,html/test1.html文件中一些资源文件或者链接地址会失效。

loadDataWithBaseURL和loadData两个方法加载的HTML代码片段的不同点在于,loadData()中的html data中不能包含’#’, ‘%’, ‘\’, ‘?’四中特殊字符,在平时测试时,你的数据时,你的数据里含有这些字符,但不会出问题,当出问题时,你可以替换下。

%,会报找不到页面错误,页面全是乱码。乱码样式见符件。

#,会让你的goBack失效,但canGoBAck是可以使用的。于是就会产生返回按钮生效,但不能返回的情况。

WebView内容的处理

android 中webView控件 padding不起作用
在一个布局文件中有一个WebView,想使用padding属性让左右向内留出一些空白,但是padding属性不起左右,内容照样贴边显示,反而移动了右边滚动条的位置。android的bug,用一个外围的layout包含webview,可以有所改进,但不能完全解决。其实正确的做法是在webView的加载的css中增加padding,没必要为了padding而更改xml布局文件。

重写shouldOverrideUrlLoading时指定url

指定只有url里包含eoe.cn的时候才在webview里打开,否则还是启动浏览器打开.

1
2
3
4
5
6
7
8
9
10
11
12
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
     LogUtil.i( this "url="    url);
     if  ( url.contains( "eoe.cn" ) ==  true ){
         view.loadUrl(url);
         return  true ;
     } else {
         Intent  in  new  Intent (Intent.ACTION_VIEW , Uri.parse(url));
         startActivity( in );
         return  true ;
     }
}

android:scrollbarStyle控制滚动条位置

WebView有一个设置滚动条位置的属性:android:scrollbarStyle 可以是insideOverlay可以是outsideOverlay,两个的区别是SCROLLBARS_INSIDE_OVERLAY的样式是滚动条在整个page里,类似css中的padding,看代码下的这个图吧,很清晰.

mWebView.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY);


以下转自:http://www.eoeandroid.com/thread-321414-1-1.html

浏览器控件是每个开发环境都具备的,这为马甲神功提供了用武之地,windows的有webbrowser,android和ios都有webview。只是其引擎不同,相对于微软的webbrowser,android及ios的webview的引擎都是webkit,对Html5提供支持。本篇主要介绍android的webview之强大。

A.    webview组件如何使用

1)       添加权限:AndroidManifest.xml中必须使用许可"android.permission.INTERNET",否则会出Web page not available错误。 2)       在要Activity中生成一个WebView组件:WebView webView = new WebView(this);或者可以在activitylayout文件里添加webview控件:

<WebView

android:id="@+id/wv"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent"

    android:text="@string/hello"

    />
3)       设置WebView基本信息:
          如果访问的页面中有Javascript,则webview必须设置支持Javascript
          webview.getSettings().setJavaScriptEnabled(true);  
          触摸焦点起作用
          requestFocus();
          取消滚动条
          this.setScrollBarStyle(SCROLLBARS_OUTSIDE_OVERLAY);

4)       设置WevView要显示的网页:
          互联网用:webView.loadUrl("http://www.google.com"); 
          本地文件用:webView.loadUrl("file:///android_asset/XX.html");  本地文件存放在:assets文件中
5)       如果希望点击链接由自己处理,而不是新开Android的系统browser中响应该链接。给WebView添加一个事件监听对象(WebViewClient)并重写其中的一些方法:
shouldOverrideUrlLoading:对网页中超链接按钮的响应。当按下某个连接时WebViewClient会调用这个方法,并传递参数:按下的url。比如当webview内嵌网页的某个数字被点击时,它会自动认为这是一个电话请求,会传递urltel:123,如果你不希望如此可通过重写shouldOverrideUrlLoading函数解决:
  
[java] view plaincopyprint?

  • public boolean shouldOverrideUrlLoading(WebView view,String url){  
  •   
  •         if(url.indexOf("tel:")<0){//页面上有数字会导致连接电话  
  •   
  •             view.loadUrl(url);  
  •   
  •         }  
  •   
  •            return true;            
  •   
  •        }  

public boolean shouldOverrideUrlLoading(WebView view,String url){         if(url.indexOf("tel:")<0){//页面上有数字会导致连接电话             view.loadUrl(url);         }            return true;                  }

        另外还有其他一些可重写的方法 
1,接收到Http请求的事件
onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm)  
2,打开链接前的事件
public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return true; }
这个函数我们可以做很多操作,比如我们读取到某些特殊的URL,于是就可以不打开地址,取消这个操作,进行预先定义的其他操作,这对一个程序是非常必要的。

3,载入页面完成的事件
public void onPageFinished(WebView view, String url){ }
同样道理,我们知道一个页面载入完成,于是我们可以关闭loading条,切换程序动作。

4,载入页面开始的事件
public void onPageStarted(WebView view, String url, Bitmap favicon) { }
这个事件就是开始载入页面调用的,通常我们可以在这设定一个loading的页面,告诉用户程序在等待网络响应。

通过这几个事件,我们可以很轻松的控制程序操作,一边用着浏览器显示内容,一边监控着用户操作实现我们需要的各种显示方式,同时可以防止用户产生误操作。
      
6)       如果用webview点链接看了很多页以后,如果不做任何处理,点击系统“Back”键,整个浏览器会调用finish()而结束自身,如果希望浏览的网页回退而不是退出浏览器,需要在当前Activity中处理并消费掉该Back事件。
       覆盖Activity类的onKeyDown(int keyCoder,KeyEvent event)方法。
   [java] view plaincopyprint?

  • public boolean onKeyDown(int keyCoder,KeyEvent event){  
  •                         if(webView.canGoBack() && keyCoder == KeyEvent.KEYCODE_BACK){  
  •                                  webview.goBack();   //goBack()表示返回webView的上一页面  
  •   
  •                                 return true;  
  •                          }  
  •                          return false;  
  •                 }  

public boolean onKeyDown(int keyCoder,KeyEvent event){                         if(webView.canGoBack() && keyCoder == KeyEvent.KEYCODE_BACK){                                  webview.goBack();   //goBack()表示返回webView的上一页面                                 return true;                          }                          return false;                 }

B.    Webviewjs交互

Webview与js的双向交互才是android的webview强大所在,也是马甲精神能够彻底执行的基础保障。

首先,webview可以定义一个在其内嵌页面中可以触发的事件

[java] view plaincopyprint?

  • wv.addJavascriptInterface(new DemoJavaScriptInterface(), "demo");  
  •   
  • rivate final class DemoJavaScriptInterface  
  •   
  •    {  
  • nbsp;DemoJavaScriptInterface(){}  
  •   
  •     public void clickonAndroid( final String order){  
  •         mHandler.post(newRunnable(){  
  •             @Override  
  •             public void run(){  
  •                       jsonText="{"name":""+order+""}";  
  •                wv.loadUrl("javascript:wave("+jsonText+")");  
  •             }  
  •         });  
  •     }  

wv.addJavascriptInterface(new DemoJavaScriptInterface(), "demo");private final class DemoJavaScriptInterface    { DemoJavaScriptInterface(){}     public void clickonAndroid( final String order){         mHandler.post(newRunnable(){             @Override             public void run(){                       jsonText="{"name":""+order+""}";                wv.loadUrl("javascript:wave("+jsonText+")");             }         });     }}

通过以上代码,即可实现在其内嵌网页中触发window.demo.clickOnAndroid(str)事件并传参数str给webview。Webview接收到str之后,可以通过以上代码触发其内嵌页面中的js函数wave(str)。这样就可以实现网页触发webview的事件并传参数,webview接收参数并调用js函数。

下面看我的Html脚本:

<!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/html; charset=UTF-8">

<title>Insert title here</title>

<script type="text/javascript" src="jquery.js"></script>

<script>

function toclient()

{

    var order=$("#val").val();

window.demo.clickonAndroid(order);

   

    }

   

    function wave(str){

       //alert(str.name);

       $("#fromclient").text(str.name);

    }

</script>

</head>

    <body>这是一个html页面

    <br/>

输入一个字符串:<br/>

  <input id="val" />

        <input type="submit" value="点击提交给客户端"

        οnclick="toclient();"/>

      <br />

        显示返回:<label id="fromclient"></label>

    </body>

</html>


通过脚本看到wave(str)函数是负责将原来传给webview的数据重新拿回页面,效果图如下:


另外,如果你想获取页面的一些处理数据并交给webview客户端处理,可在wave函数里将数据alert,然后webview中重写WebChromeClient的onJsAlert函数,具体代码如下

[java] view plaincopyprint?

  • wv.setWebChromeClient(new MyWebChromeClient());  
  •   
  • final  class MyWebChromeClient extends WebChromeClient{  
  •   
  •     @Override  
  •   
  •       public booleanonJsAlert(WebView view, String url, String message, final JsResult result) {   
  •   
  • //message就是wave函数里alert的字符串,这样你就可以在android客户端里对这个数据进行处理  
  •   
  •                 result.confirm();         
  •   
  •               }   
  •   
  • return true;   
  •         }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值