編輯:關於Android編程
Android開發過程中,我們或多或少都會用到webview,使用webview來展示一些經常變動的界面更加方便簡單,也更易於維護。在使用webview來展示網頁的時候,有些時候我們需要通過JS和Android原生控件進行交互,以實現自己需要的效果或功能,本文通過一個demo簡單實現了JS和Android原生控件的交互。
界面上方是EditView和Button,下方是一個webview控件,通過輸入url,然後點擊跳轉按鈕,webview控件會加載該url,本次為了方便學習,我已經寫好了一個html文件放置在了Asset文件中,通過file:///android_asset/test.html來進行加載。然後出現四個新的按鈕,點擊不同的按鈕,會產生不同的效果。
asset文件夾下面的test.html文件
<meta charset="UTF-8" />
<meta content="EditPlus?" name="Generator" />
<meta content="" name="Author" />
<meta content="" name="Keywords" />
<meta content="" name="Description" />
<title></title>
<script>
function jsAlert(){
var r = alert("I am alert");
alert(r);
}
function jsConFirm(){
var r = confirm("I am conFirm");
alert(r);
}
function jsPrompt(){
//第一個參數是提示
//第二個參數是默認值
var r = prompt("請輸入姓名:","小明同學");
alert(r);
}
function jsJava(){
//調用java的方法,頂級對象,java方法
//可以直接訪問JSTest,這是因為JSTest掛載到js的window對象下了
JSTest.showToast("我是被JS執行的Android代碼");
}
</script>
代碼很簡單,整個界面只有四個按鈕,以及四個JS寫的方法jsAlert(),jsConFirm(),jsPrompt(),jsJava(),當點擊按鈕觸發這些方法的時候,會進一步觸發我們寫好的java代碼,具體實現請參見java代碼。
具體的java代碼
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.View;
import android.webkit.JavascriptInterface;
import android.webkit.JsPromptResult;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.EditText;
import android.widget.Toast;
public class JSActivity extends AppCompatActivity {
//assets下的文件的test.html所在的絕對路徑
private static final String DEFAULT_URL = "file:///android_asset/test.html";
private EditText et_url;
private WebView webView;
private ProgressDialog progressDialog;//加載界面的菊花
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_js);
initView();
initWebView();
}
/**
* 初始化控件
*/
private void initView() {
webView = (WebView) findViewById(R.id.webView);
et_url = (EditText) findViewById(R.id.et_url);
}
/**
* 初始化webview
*/
private void initWebView() {
//首先設置Webview支持JS代碼
webView.getSettings().setJavaScriptEnabled(true);
//Webview自己處理超鏈接(Webview的監聽器非常多,封裝一個特殊的監聽類來處理)
webView.setWebViewClient(new WebViewClient() {
/**
* 當打開超鏈接的時候,回調的方法
* WebView:自己本身webView
* url:即將打開的url
*/
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//自己處理新的url
webView.loadUrl(url);
//true就是自己處理
return true;
}
//重寫頁面打開和結束的監聽。添加友好,彈出菊花
/**
* 界面打開的回調
*/
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
//彈出菊花
progressDialog = new ProgressDialog(JSActivity.this);
progressDialog.setTitle("提示");
progressDialog.setMessage("軟軟正在拼命加載……");
progressDialog.show();
}
/**
* 界面打開完畢的回調
*/
@Override
public void onPageFinished(WebView view, String url) {
//隱藏菊花:不為空,正在顯示。才隱藏
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
}
});
//設置進度條
//WebChromeClient與webViewClient的區別
//webViewClient處理偏界面的操作:打開新界面,界面打開,界面打開結束
//WebChromeClient處理偏js的操作
webView.setWebChromeClient(new WebChromeClient() {
/**
* 進度改變的回調
* WebView:就是本身
* newProgress:即將要顯示的進度
*/
@Override
public void onProgressChanged(WebView view, int newProgress) {
if (progressDialog != null && progressDialog.isShowing())
progressDialog.setMessage("軟軟正在拼命加載……" + newProgress + "%");
}
/**
* 重寫alert、confirm和prompt的回調
*/
/**
* Webview加載html中有alert()執行的時候,回調
* url:當前Webview顯示的url
* message:alert的參數值
* JsResult:java將結果回傳到js中
*/
@Override
public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
AlertDialog.Builder builder = new AlertDialog.Builder(JSActivity.this);
builder.setTitle("提示");
builder.setMessage(message);//這個message就是alert傳遞過來的值
builder.setPositiveButton("確定", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//處理確定按鈕了,且通過jsresult傳遞,告訴js點擊的是確定按鈕
result.confirm();
}
});
builder.show();
//自己處理
return true;
}
@Override
public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {
AlertDialog.Builder builder = new AlertDialog.Builder(JSActivity.this);
builder.setTitle("提示");
builder.setMessage(message);//這個message就是alert傳遞過來的值
builder.setPositiveButton("確定", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//處理確定按鈕了,且通過jsresult傳遞,告訴js點擊的是確定按鈕
result.confirm();
}
});
builder.setNegativeButton("取消", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//處理取消按鈕,且通過jsresult傳遞,告訴js點擊的是取消按鈕
result.cancel();
}
});
builder.show();
//自己處理
return true;
}
/**
* defaultValue就是prompt的第二個參數值,輸入框的默認值
* JsPromptResult:向js回傳數據
*/
@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue,
final JsPromptResult result) {
AlertDialog.Builder builder = new AlertDialog.Builder(JSActivity.this);
builder.setTitle("提示");
builder.setMessage(message);//這個message就是alert傳遞過來的值
//添加一個EditText
final EditText editText = new EditText(JSActivity.this);
editText.setText(defaultValue);//這個就是prompt 輸入框的默認值
//添加到對話框
builder.setView(editText);
builder.setPositiveButton("確定", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//獲取edittext的新輸入的值
String newValue = editText.getText().toString().trim();
//處理確定按鈕了,且過jsresult傳遞,告訴js點擊的是確定按鈕(參數就是輸入框新輸入的值,我們需要回傳到js中)
result.confirm(newValue);
}
});
builder.setNegativeButton("取消", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//處理取消按鈕,且過jsresult傳遞,告訴js點擊的是取消按鈕
result.cancel();
}
});
builder.show();
//自己處理
return true;
}
});
//java與js回調,自定義方法
//1.java調用js
//2.js調用java
//首先java暴露接口,供js調用
/**
* obj:暴露的要調用的對象
* interfaceName:對象的映射名稱 ,object的對象名,在js中可以直接調用
* 在html的js中:JSTest.showToast(msg)
* 可以直接訪問JSTest,這是因為JSTest掛載到js的window對象下了
*/
webView.addJavascriptInterface(new Object() {
//定義要調用的方法,注意4.2及以後的則多了注釋語句@JavascriptInterface
//msg由js調用的時候傳遞
@JavascriptInterface
public void showToast(String msg) {
Toast.makeText(getApplicationContext(),
msg, Toast.LENGTH_SHORT).show();
}
}, "JSTest");
}
public void onClick(View view){
String url = et_url.getText().toString().trim();
if(TextUtils.isEmpty(url)){
url = DEFAULT_URL;
}
webView.loadUrl(url);
}
@Override
public void onBackPressed() {
if (webView.canGoBack()) {
//返回上一個頁
webView.goBack();
return ;
}
super.onBackPressed();
}
}
布局文件activity_js.xml
代碼過程描述的廢話我就不多說了,注釋寫的算是比較仔細了,另外再強調兩點需要注意的地方:
一、不要忘記通過setJavaScriptEnabled(true)設置webview支持JS代碼
二、在使用addJavascriptInterface方法添加掛載對象時,要注意在Android4.2之後需要給對象方法加上@JavascriptInterface注解。
Android布局技巧之創建高效布局
Android UI工具包提供了一些布局管理器,它們使用起來相當容易,而且,大多數的時候,你只需要使用它們最基本的特征來實現UI。執著於基本特征的使用對於創建UI來說,往
Android線程池框架下的線程池策略
線程的運行機制 1. 開啟線程過多,會消耗cpu2. 單核cpu,同一時刻只能處理一個線程,多核cpu同一時刻可以處理多個線程3. 操作系統為每個運行線程安排一
android自定義ImageView仿圖片上傳示例
看下效果圖主要看下自定義view 代碼public class ProcessImageView extends ImageView{ private Context
Android ListView性能優化實戰方案
前言:對於ListView,大家絕對都不會陌生,只要是做過Android開發的人,哪有不用ListView的呢?只要是用過ListView的人,哪有不關心對它性能優化的呢