Webview JS互动
首先要打开webview对js的支持
WebSettings settings=webView.getSettings(); settings.setJavaScriptEnabled(true);
这里加载assets文件里面一个网页
webView.loadUrl("file:///android_asset/webview.html");
在setWebChromeClient方法中重写 onJsAlert onJsConfirm onJsPrompt 方法来接收JS调用的 Alert Confirm Prompt
1 webView.setWebChromeClient(new WebChromeClient(){ 2 @Override 3 public boolean onJsAlert(WebView view, String url, String message, 4 final JsResult result) { 5 new AlertDialog.Builder(JswebActivity.this).setTitle("Alert") 6 .setMessage(message).setPositiveButton("确定", new DialogInterface.OnClickListener() { 7 8 @Override 9 public void onClick(DialogInterface dialog, int which) { 10 result.confirm(); 11 } 12 }).create().show(); 13 14 return true; 15 } 16 17 @Override 18 public boolean onJsConfirm(WebView view, String url, String message, 19 final JsResult result) { 20 new AlertDialog.Builder(JswebActivity.this).setTitle("Confirm").setMessage(message) 21 .setPositiveButton("ok", new DialogInterface.OnClickListener() { 22 23 @Override 24 public void onClick(DialogInterface dialog, int which) { 25 result.confirm(); 26 } 27 }).setNegativeButton("no", new DialogInterface.OnClickListener() { 28 29 @Override 30 public void onClick(DialogInterface dialog, int which) { 31 result.cancel(); 32 } 33 }).create().show(); 34 35 return true; 36 } 37 38 39 @Override 40 public boolean onJsPrompt(WebView view, String url, String message, 41 String defaultValue, final JsPromptResult result) { 42 43 final View v = View.inflate(JswebActivity.this, R.layout.prompt_dialog, null); 44 TextView tv=(TextView) v.findViewById(R.id.prompt_message_text); 45 tv.setText(message); 46 ((EditText) v.findViewById(R.id.prompt_input_field)).setText(defaultValue); 47 48 new AlertDialog.Builder(JswebActivity.this).setTitle("Prompt").setView(v). 49 setPositiveButton("ok", new DialogInterface.OnClickListener() { 50 51 @Override 52 public void onClick(DialogInterface dialog, int which) { 53 String value = ((EditText) v.findViewById(R.id.prompt_input_field)).getText().toString(); 54 result.confirm(value); 55 } 56 }).setNegativeButton("no", new DialogInterface.OnClickListener() { 57 58 @Override 59 public void onClick(DialogInterface dialog, int which) { 60 result.cancel(); 61 } 62 }).create().show(); 63 64 return true; 65 } 66 });
在onJsPrompt 中用到一个简单的布局 prompt_dialog.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/prompt_message_text" android:layout_width="match_parent" android:layout_height="wrap_content" /> <EditText android:id="@+id/prompt_input_field" android:layout_width="match_parent" android:layout_height="wrap_content" android:minWidth="250dp" android:selectAllOnFocus="true" android:scrollHorizontally="true"/> </LinearLayout>
在activity里面调用 网页中JS方法
webView.loadUrl("javascript:sendText()");
JS中对应的方法
function sendText() { var text=android.getText(); document.getElementById("text_msg").value=text; }
这个JS方法里面 调用了 android.getText(),这是在JS中调用activity中的方法
首先要加一个JS接口,后面加一个识别的名字,这是写的是 android
webView.addJavascriptInterface(new JsInterface(JswebActivity.this),"android");
自定义接口
public class JsInterface{ private Context context; public JsInterface(Context mcontext) { this.context = mcontext; } @JavascriptInterface public void setText(String str) { Message message=new Message(); message.what=1; message.obj=str; handler.sendMessage(message); } @JavascriptInterface public void setNum(int i) { Message message=new Message(); message.what=0; message.obj=i; handler.sendMessage(message); } @JavascriptInterface public String getText(){ return text; } @JavascriptInterface public int getNum(){ return num; } @JavascriptInterface public void finish(){ Logger.e("finish", "finish"); JswebActivity.this.finish(); } @JavascriptInterface public void setPrompt(String s){ ((Button)findViewById(R.id.btn_send)).setText(s); } }
每个方法都要加上注解 @JavascriptInterface
这里面有一个 getText()方法,返回了 当前activity里的 text的值,JS调用 android.getText() 方法获取了activity里的 text的值
网页代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <input type="text" id="text_msg" value="js text"> <button type="button" onclick="submit()">提交</button> <p></p> <input type="number" disabled id="text_num" style="width: 30px" value="1"> <button type="button" onclick="add()">+</button> <button type="button" onclick="reduce()">-</button> <p></p> =================================== <input type="text" id="text_close" value="text_"> <p></p> <button type="button" onclick="activityclose()">close</button> </body> <script type="text/javascript"> function submit() { var text=document.getElementById("text_msg").value; android.setText(text); } function add() { var num=document.getElementById("text_num").value; num++; document.getElementById("text_num").value=num; android.setNum(num); } function reduce() { var num=document.getElementById("text_num").value; num--; document.getElementById("text_num").value=num; android.setNum(num); } function activityclose() { android.finish(); } //----------------------------------------------------------------------------------------------------- function sendText() { var text=android.getText(); document.getElementById("text_msg").value=text; } function sendNum() { document.getElementById("text_close").value="sendNum"; var num=android.getNum()+""; document.getElementById("text_num").value=num; } function sendClose() { alert("This is a alert sample from html"); document.getElementById("text_close").value="close"; var close = window.confirm("需要关闭当前页面"); if(close==true){ document.getElementById("text_close").value="true close"; android.finish(); }else { document.getElementById("text_close").value="false close"; } } function sendPrompt() { var b = prompt("please input your password","aaa"); alert("your input is "+b); if (b.length>0){ android.setPrompt(b); } } </script> </html>
微信里面加载网页的时候 顶部会有一条绿色进度条 直接ProgressBar会出现问题 最终在stackoverflow 上找到了解决方法
布局
<?xml version="1.0" encoding="utf-8"?> <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"> <WebView android:id="@+id/webView" android:layout_width="match_parent" android:layout_height="match_parent" /> <ProgressBar android:id="@+id/web_bar" style="?android:attr/progressBarStyleHorizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="-7dp" android:layout_marginTop="-7dp" android:indeterminate="false" /> </RelativeLayout>
逻辑代码中 红色部分是关键,颜色随便换
web_bar.getProgressDrawable().setColorFilter(Color.RED,android.graphics.PorterDuff.Mode.SRC_IN); // 设置加载进来的页面自适应手机屏幕 settings.setUseWideViewPort(true); settings.setLoadWithOverviewMode(true); settings.setSupportZoom(true); settings.setBuiltInZoomControls(true); settings.setDisplayZoomControls(true);
在 setWebChromeClient 方法里 重写 onProgressChanged
@Override public void onProgressChanged(WebView view, int newProgress) { super.onProgressChanged(view, newProgress); web_bar.setProgress(newProgress); if (newProgress == 100) { web_bar.setVisibility(View.GONE); } else { web_bar.setVisibility(View.VISIBLE); } }
webview 有不少值得注意的地方
其一就是千万不要 把onPageFinished 当作是网页加载完成,加载过程中,它会调用好几次。onProgressChanged 里面判断 newProgress == 100 要靠谱的多
退出的时候 要把webview 销毁
@Override protected void onDestroy() { if (webView != null) webView.destroy(); super.onDestroy(); }
下面一种可能更好
@Override protected void onDestroy() { if (webView!= null){ ViewGroup viewGroup=(ViewGroup) webView.getParent(); if (viewGroup!=null) { viewGroup.removeView(webView); } webView.destroy(); } super.onDestroy(); }