Android使用webView細節
android中使用WebView細節繁多,特此記錄一個天氣視覺化折線圖,android端使用WebView載入前端H5頁面,視覺化工具使用Echarts ,api使用聚合天氣
編寫佈局 ProgressBar為進度條,可省略
<?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">
<ProgressBar
android:layout_width="match_parent"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:id="@+id/chart_bar"
android:layout_height="10dp"/>
<WebView
android:layout_width="match_parent"
android:id="@+id/fragment_webview"
android:layout_height="match_parent"/>
</LinearLayout>
H5中編寫一個測試方法供android端呼叫
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script>
/* 無參呼叫 */
function notParamFun() {
alert("網頁方法被呼叫");
}
/* 有參呼叫 */
function haveParamtestFun(data) {
alert("接收到android端的資料:" + data);
}
</script>
</html>
注意:編寫好的HTML網頁需要放入android 專案中的assets中,assets需要手動新建。
android 中java程式碼,注意loadUrl中是asset,且傳送資料必須等待網頁載入完(newProgress =100)才能進行互動並且只能傳輸字串形式。
且需要加入單引號
private ProgressBar chartBar;
private WebView fragmentWebview;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
chartBar = (ProgressBar) view.findViewById(R.id.chart_bar);
fragmentWebview = (WebView) view.findViewById(R.id.fragment_webview);
/*前端介面*/
fragmentWebview.addJavascriptInterface(this, "myWebView");
fragmentWebview.loadUrl("file:///android_asset/myWebView.html");
fragmentWebview.setWebChromeClient(new WebChromeClient() {
@Override
public void onProgressChanged(WebView view, int newProgress) {
// 當進度達到100時呼叫H5介面
if (newProgress == 100) {
fragmentWebview.loadUrl("javascript:notParamFun()");
fragmentWebview.loadUrl("javascript:haveParamtestFun('"+ "傳送String資料" +"')");
chartBar.setVisibility(View.GONE);
} else {
chartBar.setVisibility(View.VISIBLE);
chartBar.setProgress(newProgress);
}
}
});
}
/*前端呼叫的介面方法*/
@JavascriptInterface
public void getData(String title) {
new AlertDialog.Builder(getContext())
.setTitle(title)
.setMessage("前端呼叫")
.setPositiveButton("OK", null)
.create()
.show();
}
在android已經寫好網頁端呼叫介面物件myWebView,且有一個共前端呼叫的方法為getData
/*前端介面物件*/
fragmentWebview.addJavascriptInterface(this, "myWebView");
/*前端呼叫的介面方法*/
@JavascriptInterface
public void getData(String title) {
new AlertDialog.Builder(getContext())
.setTitle(title)
.setMessage("前端呼叫")
.setPositiveButton("OK", null)
.create()
.show();
}
只需在前端加入一行呼叫程式碼
<script>
//呼叫android方法,無參也需要寫上()
javascript: myWebView.getData("我是前端的title");
/* 無參呼叫 */
function notParamFun() {
alert("網頁方法被呼叫");
}
/* 有參呼叫 */
function haveParamtestFun(data) {
alert("接收到android端的資料:" + data);
}
</script>
儲存重新啟動模擬器
注意:stack加上會有堆疊顯示問題,最後去掉stack解決堆疊問題
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.staticfile.org/echarts/4.7.0/echarts.min.js"></script>
</head>
<body>
<div id="myChartPie" style="width: 100%; height: 400px; "></div>
<div></div>
</body>
<script>
var echartsPie = echarts.init(document.getElementById("myChartPie"));
var option = {
title: {
text: '武漢天氣預報'
},
tooltip: {
trigger: 'axis'
},
legend: {
data: ['最低溫度', '最高溫度']
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
xAxis: {
type: 'category',
boundaryGap: false,
data: [],
},
yAxis: {
type: 'value'
},
series: [{
name: '最低溫度',
type: 'line',
data: [],
itemStyle: {
normal: {
color: 'black',
borderColor: 'black', //拐點邊框顏色
}
},
}, {
name: '最高溫度',
type: 'line',
data: [],
itemStyle: {
normal: {
color: 'red',
borderColor: 'red', //拐點邊框顏色
}
},
}
]
};
echartsPie.setOption(option);
function javacalljs(data) {
/* 將JSON資料轉換為物件 */
data = JSON.parse(data);
var weather = data.result.future;
//時間陣列
var dateArr = [];
//最低氣溫陣列
var temLowerArr = [];
//最高氣溫陣列
var temHightArr = [];
//迴圈遍歷新增資料
weather.forEach(function(item) {
var tem = item.temperature.toString().replace("℃", "").split("/");
dateArr.push(item.date);
temLowerArr.push(tem[0]);
temHightArr.push(tem[1]);
});
option.xAxis.data = dateArr;
option.series[0].data = temLowerArr;
option.series[1].data = temHightArr;
//最後要更新圖表
echartsPie.setOption(option);
}
</script>
</html>
佈局仍然使用上次的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">
<ProgressBar
android:layout_width="match_parent"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:id="@+id/chart_bar"
android:layout_height="10dp"/>
<WebView
android:layout_width="match_parent"
android:id="@+id/fragment_webview"
android:layout_height="match_parent"/>
</LinearLayout>
java 互動程式碼,api選用聚合天氣api,網路框架使用OKHttp
private ProgressBar chartBar;
private WebView fragmentWebview;
private String apiData = "";
//請求聚合天氣API的url
private final String url = "http://apis.juhe.cn/simpleWeather/query";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
chartBar = (ProgressBar) view.findViewById(R.id.chart_bar);
fragmentWebview = (WebView) view.findViewById(R.id.fragment_webview);
RequestBody body =new FormBody.Builder()
.add("key", "你申請的key")
.add("city", "武漢")
.build();
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
client.newCall(request).enqueue(new Callback() {
/*請求失敗時的回撥*/
@Override
public void onFailure(Call call, IOException e) {
Log.e("onFailure: ", e.getMessage());
}
/*請求成功時的回撥*/
@Override
public void onResponse(Call call, Response response) throws IOException {
apiData = response.body().string();
}
});
fragmentWebview.loadUrl("file:///android_asset/myWebView.html");
fragmentWebview.setWebChromeClient(new WebChromeClient() {
@Override
public void onProgressChanged(WebView view, int newProgress) {
// 當進度達到100時傳送資料
if (newProgress == 100) {
fragmentWebview.loadUrl("javascript:javacalljs('"+ apiData +"')");
chartBar.setVisibility(View.GONE);
} else {
chartBar.setVisibility(View.VISIBLE);
chartBar.setProgress(newProgress);
}
}
});
}