- 浏览: 639476 次
文章分类
最新评论
-
netkongjian:
不错的报表工具知识分享![deyi]
报表漫谈 -
jiranjiran:
...
Eclipse + SVN + Google code 搭建代码仓库
一片WebView的好文章,直接拿过来 = =
WebView是Android中一个非常实用的组件,它和Safai、Chrome一样都是基于Webkit网页渲染引擎,可以通过加载HTML数据的方式便捷地展现软件的界面。使用WebView开发软件有一下几个优点:
1.可以打开远程URL页面,也可以加载本地HTML数据;
2.可以无缝的在java和javascript之间进行交互操作;
3.高度的定制性,可根据开发者的需要进行多样性定制。
下面就通过例子来介绍一下WebView的使用方法。
我们先建一个webview项目,项目结构如左图:
在这个项目中,我们会先进入MainActivity这个导航界面(上边右图),通过点击不同按钮转向不同的Activity,下面分别简单介绍一下这几个Activity的所要演示的功能:
LoadActivity:主要演示加载网络页面和WebView的一些基本设置;
CaptureActivity:主要演示WebView的截图的功能;
FileActivity:主要演示访问本地文件的功能;
JSActivity:主要演示WebView对JS的支持以及JS和Java之间的互相调用;
接下来,我们会逐一分析各个Activity的相关信息:
LoadActivity:
与之对应的布局文件为load.xml,演示效果如下:
我们在文本框中输入URL,然后点击“load”按钮,然后由WebView加载相应的页面,在加载过程中,根据加载进度更新窗口的进度条。由于布局相对简单,我们主要来看一下LoadActivity.java的代码:
- packagecom.scott.webview;
- importandroid.app.Activity;
- importandroid.os.Bundle;
- importandroid.view.KeyEvent;
- importandroid.view.View;
- importandroid.view.Window;
- importandroid.webkit.WebChromeClient;
- importandroid.webkit.WebSettings;
- importandroid.webkit.WebView;
- importandroid.webkit.WebViewClient;
- importandroid.widget.Button;
- importandroid.widget.EditText;
- publicclassLoadActivityextendsActivity{
- privateWebViewwebView;
- @Override
- protectedvoidonCreate(BundlesavedInstanceState){
- super.onCreate(savedInstanceState);
- //设置窗口风格为进度条
- getWindow().requestFeature(Window.FEATURE_PROGRESS);
- setContentView(R.layout.load);
- webView=(WebView)findViewById(R.id.webView);
- WebSettingssettings=webView.getSettings();
- settings.setSupportZoom(true);//支持缩放
- settings.setBuiltInZoomControls(true);//启用内置缩放装置
- settings.setJavaScriptEnabled(true);//启用JS脚本
- webView.setWebViewClient(newWebViewClient(){
- //当点击链接时,希望覆盖而不是打开新窗口
- @Override
- publicbooleanshouldOverrideUrlLoading(WebViewview,Stringurl){
- view.loadUrl(url);//加载新的url
- returntrue;//返回true,代表事件已处理,事件流到此终止
- }
- });
- //点击后退按钮,让WebView后退一页(也可以覆写Activity的onKeyDown方法)
- webView.setOnKeyListener(newView.OnKeyListener(){
- @Override
- publicbooleanonKey(Viewv,intkeyCode,KeyEventevent){
- if(event.getAction()==KeyEvent.ACTION_DOWN){
- if(keyCode==KeyEvent.KEYCODE_BACK&&webView.canGoBack()){
- webView.goBack();//后退
- returntrue;//已处理
- }
- }
- returnfalse;
- }
- });
- webView.setWebChromeClient(newWebChromeClient(){
- //当WebView进度改变时更新窗口进度
- @Override
- publicvoidonProgressChanged(WebViewview,intnewProgress){
- //Activity的进度范围在0到10000之间,所以这里要乘以100
- LoadActivity.this.setProgress(newProgress*100);
- }
- });
- finalEditTexturl=(EditText)findViewById(R.id.url);
- ButtonloadURL=(Button)findViewById(R.id.loadURL);
- loadURL.setOnClickListener(newView.OnClickListener(){
- @Override
- publicvoidonClick(Viewv){
- webView.loadUrl(url.getText().toString());//加载url
- webView.requestFocus();//获取焦点
- }
- });
- }
- }
可以看到,我们使用loadUrl方法加载一个url页面,然后重写WebChromeClient的onProgressChanged方法更新进度条。loadUrl方法除了能加载远程页面,还能加载本地的文件:
- //加载assets中的html文件
- webView.loadUrl("file:///android_asset/index.html");
- //加载sdcard中的html文件
- webView.loadUrl("file:///mnt/sdcard/index.html");
这些都会在后边的示例中使用到。
CaptureActivity:
与之对应的布局文件为capture.xml,也比较简单,它的演示效果如下:
记得在AndroidManifest.xml中加入对sdcard的写权限:
- <uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
截图成功后,在/mnt/sdcard目录下会生成一个当前网页的截图,如图:
我们导出一下,看看是不是当前的网页界面:
整个过程操作已经完成了,让我们来看一下CaptureActivity.java的代码:
- packagecom.scott.webview;
- importjava.io.FileOutputStream;
- importandroid.app.Activity;
- importandroid.graphics.Bitmap;
- importandroid.graphics.Canvas;
- importandroid.graphics.Picture;
- importandroid.os.Bundle;
- importandroid.util.Log;
- importandroid.view.View;
- importandroid.webkit.WebView;
- importandroid.widget.Button;
- importandroid.widget.Toast;
- publicclassCaptureActivityextendsActivity{
- privatestaticfinalStringTAG="CAPTURE";
- privateWebViewwebView;
- @Override
- protectedvoidonCreate(BundlesavedInstanceState){
- super.onCreate(savedInstanceState);
- setContentView(R.layout.capture);
- webView=(WebView)findViewById(R.id.webView);
- webView.loadUrl("http://www.baidu.com");
- Buttoncapture=(Button)findViewById(R.id.capture);
- capture.setOnClickListener(newView.OnClickListener(){
- @Override
- publicvoidonClick(Viewv){
- //取得android.graphics.Picture实例
- Picturepicture=webView.capturePicture();
- intwidth=picture.getWidth();
- intheight=picture.getHeight();
- if(width>0&&height>0){
- //创建指定高宽的Bitmap对象
- Bitmapbitmap=Bitmap.createBitmap(width,height,Bitmap.Config.ARGB_8888);
- //创建Canvas,并以bitmap为绘制目标
- Canvascanvas=newCanvas(bitmap);
- //将WebView影像绘制在Canvas上
- picture.draw(canvas);
- try{
- StringfileName="/sdcard/webview_capture.jpg";
- FileOutputStreamfos=newFileOutputStream(fileName);
- //压缩bitmap到输出流中
- bitmap.compress(Bitmap.CompressFormat.PNG,90,fos);
- fos.close();
- Toast.makeText(CaptureActivity.this,"CAPTURESUCCESS",Toast.LENGTH_LONG).show();
- }catch(Exceptione){
- Log.e(TAG,e.getMessage());
- }
- }
- }
- });
- }
- }
FileActivity:
这个界面没有布局文件,在代码中完成,它将演示如何加载一段html代码,并应用刚才生成的网页截图,效果如下图:
在这个过程中,我们加载了截图,并给图加上了红色的边框,CaptureActivity.java代码如下:
- packagecom.scott.webview;
- importandroid.app.Activity;
- importandroid.os.Bundle;
- importandroid.webkit.WebView;
- publicclassFileActivityextendsActivity{
- @Override
- protectedvoidonCreate(BundlesavedInstanceState){
- super.onCreate(savedInstanceState);
- WebViewwebView=newWebView(this);
- webView.getSettings().setAllowFileAccess(true);//默认就是启用的,这里只是强调一下
- StringbaseURL="file:///mnt/sdcard/";//根URL
- Stringhtml="<html><body>"
- +"<h3>imagefromsdcard:<h3><br/>"
- +"<imgsrc='webview_capture.jpg'style='border:2pxsolid#FF0000;'/>"
- +"</body></html>";
- //加载相对于根URL下的数据,historyUrl设为null即可
- webView.loadDataWithBaseURL(baseURL,html,"text/html","utf-8",null);
- setContentView(webView);
- }
- }
如果将html文本保存成.html文件,放于/mnt/sdcard目录下,然后用以下方式加载也能达到相同的效果:
- webView.loadUrl("file:///mnt/sdcard/index.html");
接下来是最后一个示例:JSActivity,也是最精彩的示例,演示如何在JS和Java之间通信,我们来看一下演示过程,如图:
然后谈谈我们的执行过程,我们需要在Java代码中设置WebView的一些事件的响应,比如alert、confirm以及prompt这些JS事件,让它们按照我们的要求呈现给用户,然后我们需要定义一个Java和JS之间的接口对象,当我们加载完一个html文档后,根据这个对象的接口名称就可以在文档的JS代码中轻松的调用这个接口对象的方法,执行Java代码,我们也可以在Java端执行html文档中的JS代码。下面我们将通过代码来证实这一过程:
JSActivity.java代码如下:
- packagecom.scott.webview;
- importjava.util.ArrayList;
- importjava.util.List;
- importandroid.app.Activity;
- importandroid.app.AlertDialog;
- importandroid.content.DialogInterface;
- importandroid.os.Bundle;
- importandroid.os.Handler;
- importandroid.os.Message;
- importandroid.util.Log;
- importandroid.view.LayoutInflater;
- importandroid.view.View;
- importandroid.view.Window;
- importandroid.webkit.JsPromptResult;
- importandroid.webkit.JsResult;
- importandroid.webkit.WebChromeClient;
- importandroid.webkit.WebView;
- importandroid.widget.EditText;
- importandroid.widget.Toast;
- publicclassJSActivityextendsActivity{
- privatestaticfinalStringTAG="JSActivity";
- privateWebViewwebView;
- privateHandlerhandler=newHandler(){
- publicvoidhandleMessage(android.os.Messagemsg){
- intindex=msg.arg1;
- JSActivity.this.setProgress(index*1000);
- };
- };
- @Override
- publicvoidonCreate(BundlesavedInstanceState){
- super.onCreate(savedInstanceState);
- getWindow().requestFeature(Window.FEATURE_PROGRESS);
- webView=newWebView(this);
- webView.getSettings().setJavaScriptEnabled(true);
- webView.addJavascriptInterface(newObject(){
- @SuppressWarnings("unused")
- publicList<String>getList(){
- List<String>list=newArrayList<String>();
- for(inti=0;i<=10;i++){
- try{
- Thread.sleep(200);
- }catch(InterruptedExceptione){
- Log.e(TAG,"error:"+e.getMessage());
- }
- list.add("currentindexis:"+i);
- //不能在此直接调用Activity.setProgress,否则会报以下错误
- //Onlytheoriginalthreadthatcreatedaviewhierarchycantouchitsviews.
- Messagemsg=handler.obtainMessage();
- msg.arg1=i;
- handler.sendMessage(msg);
- }
- success();
- returnlist;
- }
- publicvoidsuccess(){
- //由Java代码调用JS函数
- webView.loadUrl("javascript:success('congratulations')");
- }
- },"bridge");
- webView.setWebChromeClient(newWebChromeClient(){
- @Override
- publicbooleanonJsAlert(WebViewview,Stringurl,Stringmessage,finalJsResultresult){
- newAlertDialog.Builder(JSActivity.this)
- .setTitle("alert")
- .setMessage(message)
- .setPositiveButton("YES",newDialogInterface.OnClickListener(){
- @Override
- publicvoidonClick(DialogInterfacedialog,intwhich){
- //处理结果为确定状态同时唤醒WebCore线程
- result.confirm();
- }
- }).create().show();
- returntrue;//已处理
- }
- @Override
- publicbooleanonJsConfirm(WebViewview,Stringurl,Stringmessage,finalJsResultresult){
- newAlertDialog.Builder(JSActivity.this)
- .setTitle("confirm")
- .setMessage(message)
- .setPositiveButton("YES",newDialogInterface.OnClickListener(){
- @Override
- publicvoidonClick(DialogInterfacedialog,intwhich){
- Toast.makeText(JSActivity.this,"youclickedyes",0).show();
- result.confirm();
- }
- })
- .setNegativeButton("NO",newDialogInterface.OnClickListener(){
- @Override
- publicvoidonClick(DialogInterfacedialog,intwhich){
- //处理结果为取消状态同时唤醒WebCore线程
- result.cancel();
- }
- }).create().show();
- returntrue;
- }
- @Override
- publicbooleanonJsPrompt(WebViewview,Stringurl,Stringmessage,StringdefaultValue,
- finalJsPromptResultresult){
- LayoutInflaterinflater=getLayoutInflater();
- Viewprompt=inflater.inflate(R.layout.prompt,null);
- finalEditTexttext=(EditText)prompt.findViewById(R.id.prompt_input);
- text.setHint(defaultValue);
- newAlertDialog.Builder(JSActivity.this)
- .setTitle("prompt")
- .setView(prompt)
- .setPositiveButton("YES",newDialogInterface.OnClickListener(){
- @Override
- publicvoidonClick(DialogInterfacedialog,intwhich){
- //记录结果
- result.confirm(text.getText().toString());
- }
- })
- .setNegativeButton("NO",newDialogInterface.OnClickListener(){
- @Override
- publicvoidonClick(DialogInterfacedialog,intwhich){
- result.cancel();
- }
- }).create().show();
- returntrue;
- }
- });
- //加载assets中的html文件
- webView.loadUrl("file:///android_asset/index.html");
- setContentView(webView);
- }
- }
需要注意的是,在重写onJsAlert、onJsConfirm、onJsPrompt这几个方法中,不要忘了用JsResult.confirm()或JsResult.cancel()处理结果,否则页面就不能再响应接下的事件了,关于这一点,我们可以看一下JsResult的代码:
- /**
- *Handleaconfirmationresponsefromtheuser.
- */
- publicfinalvoidconfirm(){
- mResult=true;
- wakeUp();
- }
- /**
- *Handletheresultiftheusercancelledthedialog.
- */
- publicfinalvoidcancel(){
- mResult=false;
- wakeUp();
- }
可以看到confirm和cancel方法都涉及到了一个wakeUp方法,这个方法主要作用是唤醒WebCore线程,定义如下:
- /*WakeuptheWebCorethread.*/
- protectedfinalvoidwakeUp(){
- if(mReady){
- synchronized(mProxy){
- mProxy.notify();
- }
- }else{
- mTriedToNotifyBeforeReady=true;
- }
- }
所以朋友们如果要重写这几个方法时要切记处理JsResult这个对象实例。
我们在处理onJsPrompt时,使用了自定义的界面,加载的是/res/layout/prompt.xml,定义如下:
- <?xmlversion="1.0"encoding="utf-8"?>
- <LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content">
- <EditText
- android:id="@+id/prompt_input"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"/>
- </LinearLayout>
在JSActivity.java代码中,我们注意到WebView组件加载了assets中的index.html,它包含与Java交互的JS代码,如下:
- <html>
- <head>
- <scripttype="text/javascript">
- functiondoAlert(){
- alert("hello!");
- }
- functiondoConfirm(){
- confirm("areyousure?");
- }
- functiondoPrompt(){
- varval=prompt("what'syourname?");
- if(val){
- alert("yournameis:"+val);
- }
- }
- functiongetList(){
- //使用java和javascript的接口bridge的方法获取集合
- varlist=window.bridge.getList();
- varresult=document.getElementById("result");
- for(vari=0;i<list.size();i++){
- vardiv=document.createElement("div");
- div.innerHTML=list.get(i).toString();
- result.appendChild(div);
- }
- }
- functionsuccess(msg){
- alert(msg);
- }
- </script>
- </head>
- <bodybackground="black">
- <inputtype="button"value="alert"onclick="doAlert()"/><br/>
- <inputtype="button"value="confirm"onclick="doConfirm()"/><br/>
- <inputtype="button"value="prompt"onclick="doPrompt()"/><br/>
- <inputtype="button"value="getList"onclick="getList()"/><br/>
- <divid="result"></div>
- </body>
- </html>
转载:http://blog.csdn.net/liuhe688/article/details/6549263
相关推荐
android webview input=file 失效解决方案
最近因为赶项目进度,因此将本来要用原生控件实现的界面,自己做了H5并嵌入webview中。...具体可以理解为 重写webview 的WebChromeClient ,废话不多说直接贴代码: private ValueCallback<Uri> mUploadMessage; p
android webview 因iframe+target=“_blank “ 导致的页面无法正常打开或获取不到调整url
解决webView不支持网页input type="file"上传功能。接个文章搜索,自己写的代码,确保可以使用。
解决在webview中input标签type="file"不能使用的问题
主要介绍了Android WebView 不支持 H5 input type="file" 解决方法,需要的朋友可以参考下
webview 直接加载JS
判断webview什么时间加载完成,==========================================================================
crosswalk-webview 比android原生的webview更好用速度更快,支持富文本显示,能够更好的支持富文本网页
mWebView = (WebView)findViewById(R.id.web_view); mWebView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY); mWebView.getSettings().setBuiltInZoomControls(true); mWebView.getSettings()....
虽然在 Webview中无法直接拦截 ajax请求(其实在shouldInterceptRequest 中是可以收到ajax请求的,但是遗憾的是取不到请求参数,这样也是没有意义的), 我们可以转换思路,能不能在js中将所有的请求转发到native中...
解决webView与scrollView结合一起滑动webview一片空白
很简单的webview浏览器,一看就会,api15-20平台
1.避免在xml直接写webview控件,这样会引用activity,所以在xml写一个LinearLayout,然后 linearLayout.addView(new MyWebview(getApplicationContext())); 这样动态生成webview就能避免内存泄漏,可是这样会导致...
uniapp 使用webView通讯
Android使用WebView获取网页的源码,将WebView封装进ArthurWebView,直接创建并初始化即可使用!
这时我们利用启动页或引导页或中间的广告页的时间来预加载webview,利用View.gone,View.visible来实现控件类的隐藏与显示,这样在启动后得到的主页就是一个已经加载好的页面了。此例中加载新浪这样的比较大的网站,...
android system webview 适配系统>=5.0
WebView基本使用 WebView是View的一个子类,可以让你在activity中显示网页 可以在布局文件中写入WebView:比如下面这个写了一个填满整个屏幕的WebView: <?xml version=1.0 encoding=utf-8?> <WebView ...