如果感覺略有用處地沮,點(diǎn)贊支持下作者。上一篇將關(guān)于 WebView 的設(shè)置仔細(xì)的捋了一遍瞧预,我們通過 WebViewController 這個(gè)類完成了所有 WebView 的設(shè)置谱净,并且在布局的時(shí)候,只需在布局文件中引入這個(gè)類的完整包名噪舀,前提是這個(gè)類要繼承于 WebView魁淳,就可以完成所有 WebView 的設(shè)置,具體可參考上一篇 當(dāng)下主流 APP与倡,Hybrid app 中需要熟練掌握的交互知識(shí)(一) 其實(shí)有人就說到了界逛,現(xiàn)在有現(xiàn)成的框架可,那我的出發(fā)點(diǎn)是從自己動(dòng)手開始纺座,再去接觸框架,這個(gè)系列我們一步步來息拜!
那么本篇將就以下幾點(diǎn)展開:
頁面布局相同情況下Activity 的 共用問題。
在原生與網(wǎng)頁混合的開發(fā)狀態(tài)下净响,如何確定頁面跳轉(zhuǎn)以及參數(shù)傳遞少欺。
根據(jù)服務(wù)端發(fā)送的 Js 接口名去做具體實(shí)現(xiàn)
Activity 共用
這是當(dāng)下很多 WebApp 都在使用的一個(gè)套路,除了避免了創(chuàng)建多個(gè) Activity 后影響性能之外馋贤,還可以保持項(xiàng)目「友好」的結(jié)構(gòu)赞别!這樣的處理大多適應(yīng)于這樣的場(chǎng)景:
頁面布局上方只有一個(gè) ToolBar 或者 ActionBar 等等的標(biāo)題欄
下方則是一個(gè) WebView 用于呈現(xiàn)網(wǎng)頁內(nèi)容
如此則可以將共同的屬性提取出來,WebView 則不用管配乓,都是一致的東西氯庆。ToolBar 上無論是標(biāo)題還是按鈕的設(shè)置,當(dāng)點(diǎn)擊了某處后我們會(huì)進(jìn)入我們?cè)诒镜貙?shí)現(xiàn)的網(wǎng)頁接口扰付,具體的原理請(qǐng)看下面的詳細(xì)解釋堤撵!
一 、建立共用的 Activity:
我們將之命名為 NewWebViewActivity
//獲取到消息處理類傳過來的 url 網(wǎng)址
String url = getIntent().getStringExtra("url");
//獲取到消息處理類傳過來的動(dòng)畫操作
int anim = getIntent().getIntExtra("animation", 0);
if (url == null) {
finish();
}else if (url.equals(Constants.urlHostBase + Constants.urlLogIn)){
baseWebView.loadUrl(url);
topToolbar.setVisibility(View.GONE);
} else {
baseWebView.loadUrl(url);
//用動(dòng)畫文件判斷新開頁面
if (anim == R.anim.slide_right_out) { //當(dāng)所有的新開頁面 是從右往左打開時(shí)(表示新開頁面)
//添加返回按鈕
backImageView.setImageResource(R.drawable.returns);
//變?yōu)轱@示狀態(tài)
backImageView.setVisibility(View.VISIBLE);
//返回鍵點(diǎn)擊事件
backImageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish(); //關(guān)閉頁面
//設(shè)置頁面退出動(dòng)畫為從左往右退出
overridePendingTransition(R.anim.none, R.anim.slide_right_out);
}
});
}
}
可以看到羽莺,并沒有多少邏輯实昨。我們這樣就可以所有新開的頁面添加一個(gè)返回鍵了,前提是有一個(gè)消息處理的類來完成打開頁面的 url 參數(shù)設(shè)置盐固,以及動(dòng)畫參數(shù)設(shè)置荒给,其實(shí)實(shí)現(xiàn)起來也是很簡(jiǎn)單!往下看
二 刁卜、建立共用的 Activity 的布局:
我們緊接著需要將我們這個(gè) Activity 布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_new_web_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:theme="@android:style/Animation.Toast"
android:background="@android:color/white"
tools:context="com.lansum.eip.activity.NewWebViewActivity">
<!-- 標(biāo)題欄 -->
<android.support.v7.widget.Toolbar
android:id="@+id/web_top_toolbar"
android:layout_width="match_parent"
android:layout_height="70dp"
android:layout_alignParentTop="true"
android:background="#00a6ff"/>
<!-- WebView -->
<com.lansum.eip.webview.WebViewController
android:id="@+id/base_web_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/web_top_toolbar" />
<!-- 標(biāo)題欄右上角圖片點(diǎn)擊按鈕 默認(rèn)隱藏狀態(tài) 下同 -->
<ImageView
android:id="@+id/right_Button"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_alignRight="@id/web_top_toolbar"
android:layout_alignTop="@id/web_top_toolbar"
android:layout_marginRight="16dp"
android:layout_marginTop="30dp"
android:visibility="gone" />
<!-- 標(biāo)題欄正中顯示的標(biāo)題 根據(jù)點(diǎn)擊區(qū)域切換標(biāo)題內(nèi)容 -->
<TextView
android:id="@+id/toolbar_text_top"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@id/web_top_toolbar"
android:layout_centerHorizontal="true"
android:layout_marginTop="32dp"
android:textColor="@android:color/white"
android:textSize="18sp" />
<!-- 標(biāo)題欄左上角用于關(guān)閉打來頁面的圖片按鈕 -->
<ImageView
android:id="@+id/back_web"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_alignLeft="@id/web_top_toolbar"
android:layout_alignTop="@id/web_top_toolbar"
android:layout_marginLeft="16dp"
android:layout_marginTop="30dp"
android:visibility="gone" />
<!-- 右上角文字點(diǎn)擊按鈕 -->
<TextView
android:id="@+id/right_Button_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignRight="@id/web_top_toolbar"
android:layout_alignTop="@id/web_top_toolbar"
android:layout_marginRight="16dp"
android:layout_marginTop="32dp"
android:textColor="@android:color/white"
android:textSize="18sp"
android:visibility="gone" />
</RelativeLayout>
布局文件很簡(jiǎn)單志电,我們將標(biāo)題欄上正中標(biāo)題,左上角關(guān)閉頁面的圖片點(diǎn)擊按鈕蛔趴,右上角的文字提交按鈕以及圖片點(diǎn)擊按鈕都放在了布局中挑辆,那接下來就是如何去控制他們的顯示時(shí)機(jī),以及按下后的反饋了!
建立好了這個(gè)用于展示我們所有網(wǎng)頁的共用 Activity 后鱼蝉,就是我們本篇的核心類了洒嗤,敲黑板!魁亦!
核心類 HtmlMessageForLocal
在開始之前我們先將思路捋清楚
處理所有網(wǎng)頁的接口實(shí)現(xiàn)渔隶,以及跳轉(zhuǎn)操作和添加標(biāo)題欄上的按鈕添加。
此類用于接收我們點(diǎn)擊或打開 WebView 服務(wù)端暴漏給我們的接口洁奈,我們負(fù)責(zé)具體實(shí)現(xiàn)间唉!
將我們實(shí)現(xiàn)的方法上加上 @JavascriptInterface 注解
此注解表明所有服務(wù)端 Js 接口,都會(huì)進(jìn)入我們自定義的這個(gè)方法里找同名方法利术,直接執(zhí)行里面的邏輯终吼!
好了,通過以上說明相信明眼的你可以發(fā)現(xiàn)氯哮,這是一個(gè)網(wǎng)頁與我們本地的交互的核心類,所有的交互邏輯實(shí)現(xiàn)都需要在這里進(jìn)行商佛!
接下來我們分層進(jìn)行喉钢,一層層,一個(gè)個(gè)方法的具體實(shí)現(xiàn)步驟良姆,來剖析整個(gè)過程肠虽。
一 、判斷接口名執(zhí)行具體的方法:
@JavascriptInterface
public void callHandler(final String methodName, final String data, final String callbackName) {
Log.e(TAG, "Method:" + methodName);
if (methodName.equals("openAttendanceFromJS")) {
openAttendanceFromJS(data); // 打開新窗口
}
}
這里只是起到了判斷作用玛追,特定的方法執(zhí)行特定的操作税课,就比如上面這個(gè)方法,只負(fù)責(zé)用戶點(diǎn)擊了 WebView 去打開新的 WebView 的所有操作痊剖。
如何判斷
/**
* Js 與 Native(android 原生交互)
* Native 調(diào)用 JS 方法
* @param methodName Js 方法名
* @param data 需要用到的數(shù)據(jù) 比如圖片資源需要傳遞的數(shù)據(jù) 以下代碼的實(shí)體類為 RightInfo
我們需要聲明一個(gè)實(shí)體類 用到什么數(shù)據(jù)資源就傳給這個(gè)參數(shù)
* @param callbackName 回調(diào)的方法名 這里具體用不到
*/
@JavascriptInterface
public void callHandler(final String methodName, final String data, final String callbackName) {
Log.e(TAG, "Method:" + methodName);
if (methodName.equals("openAttendanceFromJS")) {
openAttendanceFromJS(data); // 打開新窗口
} else if (methodName.equals("addRightBarButtonItemFromJS")) {
addRightBarButtonItemFromJS(data);// 添加右上角按鈕
}
/**
* 打開新窗口
* @param url
*/
protected void openAttendanceFromJS(String url) {
Log.i("js", url);
// TODO Auto-generated method stub
Intent intent = new Intent(ActivityCollector.getTopActivity(), NewWebViewActivity.class);
intent.putExtra("url", url);
intent.putExtra("animation", R.anim.slide_right_out);
intent.putExtra("animation", R.anim.slide_right_in);
ActivityCollector.getTopActivity().startActivity(intent);
}
/**
* 設(shè)置右上角圖片按鈕
* @param data
*/
protected void addRightBarButtonItemFromJS(String data) {
topRightImage.setBackgroundResource(imageId); //找到圖片按鈕資源
topRightImage.setVisibility(View.VISIBLE); //設(shè)置為可見狀態(tài)
topRightImage.setOnClickListener(new View.OnClickListener() { //此按鈕點(diǎn)擊事件
@Override
public void onClick(View v) {
Activity activity = ActivityCollector.getTopActivity();//獲取到棧頂 Activity
activity.runOnUiThread(new Runnable() { //強(qiáng)制運(yùn)行到主線程
@Override
public void run() {
//找到共用打的 WebView
ActivityCollector.getTopActivity().findViewById(R.id.base_web_view);
activity.overridePendingTransition(R.anim.push_bottom_out, R.anim.push_bottom_in);
//找到對(duì)應(yīng) web url網(wǎng)址
baseWebView.loadUrl("javascript:" + rightInfo.funcName);
}
});
}
});
}
在這里用兩個(gè)方法舉例韩玩,重要的步驟在這里都呈現(xiàn)了出來,根據(jù)我們服務(wù)端和 Android 端的需求做相應(yīng)邏輯和方法的疊加就可以了陆馁!
總結(jié)
此次在這里將 Js 與 Native 的交互做了一個(gè)簡(jiǎn)單總結(jié)記錄找颓,整理了通用流程和思想,下個(gè)系列將使用當(dāng)下比較流行的 Hybrid APP 框架來實(shí)現(xiàn)一個(gè)總體的處理流程叮贩。