如果感覺(jué)略有用處,點(diǎn)贊支持下作者。上一篇將關(guān)于 WebView 的設(shè)置仔細(xì)的捋了一遍,我們通過(guò) WebViewController 這個(gè)類完成了所有 WebView 的設(shè)置,并且在布局的時(shí)候,只需在布局文件中引入這個(gè)類的完整包名,前提是這個(gè)類要繼承于 WebView,就可以完成所有 WebView 的設(shè)置,具體可參考上一篇 當(dāng)下主流 APP,Hybrid app 中需要熟練掌握的交互知識(shí)(一) 其實(shí)有人就說(shuō)到了,現(xiàn)在有現(xiàn)成的框架可,那我的出發(fā)點(diǎn)是從自己動(dòng)手開(kāi)始,再去接觸框架,這個(gè)系列我們一步步來(lái)!
那么本篇將就以下幾點(diǎn)展開(kāi):
頁(yè)面布局相同情況下Activity 的 共用問(wèn)題。
在原生與網(wǎng)頁(yè)混合的開(kāi)發(fā)狀態(tài)下,如何確定頁(yè)面跳轉(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)景:
頁(yè)面布局上方只有一個(gè) ToolBar 或者 ActionBar 等等的標(biāo)題欄
下方則是一個(gè) WebView 用于呈現(xiàn)網(wǎng)頁(yè)內(nèi)容
如此則可以將共同的屬性提取出來(lái),WebView 則不用管,都是一致的東西。ToolBar 上無(wú)論是標(biāo)題還是按鈕的設(shè)置,當(dāng)點(diǎn)擊了某處后我們會(huì)進(jìn)入我們?cè)诒镜貙?shí)現(xiàn)的網(wǎng)頁(yè)接口,具體的原理請(qǐng)看下面的詳細(xì)解釋!
一 、建立共用的 Activity:
我們將之命名為 NewWebViewActivity
//獲取到消息處理類傳過(guò)來(lái)的 url 網(wǎng)址
String url = getIntent().getStringExtra("url");
//獲取到消息處理類傳過(guò)來(lái)的動(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)畫文件判斷新開(kāi)頁(yè)面
if (anim == R.anim.slide_right_out) { //當(dāng)所有的新開(kāi)頁(yè)面 是從右往左打開(kāi)時(shí)(表示新開(kāi)頁(yè)面)
//添加返回按鈕
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)閉頁(yè)面
//設(shè)置頁(yè)面退出動(dòng)畫為從左往右退出
overridePendingTransition(R.anim.none, R.anim.slide_right_out);
}
});
}
}
可以看到,并沒(méi)有多少邏輯。我們這樣就可以所有新開(kāi)的頁(yè)面添加一個(gè)返回鍵了,前提是有一個(gè)消息處理的類來(lái)完成打開(kāi)頁(yè)面的 url 參數(shù)設(shè)置,以及動(dòng)畫參數(shù)設(shè)置,其實(shí)實(shí)現(xiàn)起來(lái)也是很簡(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)閉打來(lái)頁(yè)面的圖片按鈕 -->
<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)閉頁(yè)面的圖片點(diǎn)擊按鈕,右上角的文字提交按鈕以及圖片點(diǎn)擊按鈕都放在了布局中,那接下來(lái)就是如何去控制他們的顯示時(shí)機(jī),以及按下后的反饋了!
建立好了這個(gè)用于展示我們所有網(wǎng)頁(yè)的共用 Activity 后,就是我們本篇的核心類了,敲黑板?。?/p>
核心類 HtmlMessageForLocal
在開(kāi)始之前我們先將思路捋清楚
處理所有網(wǎng)頁(yè)的接口實(shí)現(xiàn),以及跳轉(zhuǎn)操作和添加標(biāo)題欄上的按鈕添加。
此類用于接收我們點(diǎn)擊或打開(kāi) WebView 服務(wù)端暴漏給我們的接口,我們負(fù)責(zé)具體實(shí)現(xiàn)!
將我們實(shí)現(xiàn)的方法上加上 @JavascriptInterface 注解
此注解表明所有服務(wù)端 Js 接口,都會(huì)進(jìn)入我們自定義的這個(gè)方法里找同名方法,直接執(zhí)行里面的邏輯!
好了,通過(guò)以上說(shuō)明相信明眼的你可以發(fā)現(xiàn),這是一個(gè)網(wǎng)頁(yè)與我們本地的交互的核心類,所有的交互邏輯實(shí)現(xiàn)都需要在這里進(jìn)行!
接下來(lái)我們分層進(jìn)行,一層層,一個(gè)個(gè)方法的具體實(shí)現(xiàn)步驟,來(lái)剖析整個(gè)過(guò)程。
一 、判斷接口名執(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); // 打開(kāi)新窗口
}
}
這里只是起到了判斷作用,特定的方法執(zhí)行特定的操作,就比如上面這個(gè)方法,只負(fù)責(zé)用戶點(diǎn)擊了 WebView 去打開(kāi)新的 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); // 打開(kāi)新窗口
} else if (methodName.equals("addRightBarButtonItemFromJS")) {
addRightBarButtonItemFromJS(data);// 添加右上角按鈕
}
/**
* 打開(kāi)新窗口
* @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è)置為可見(jiàn)狀態(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)了出來(lái),根據(jù)我們服務(wù)端和 Android 端的需求做相應(yīng)邏輯和方法的疊加就可以了!
總結(jié)
此次在這里將 Js 與 Native 的交互做了一個(gè)簡(jiǎn)單總結(jié)記錄,整理了通用流程和思想,下個(gè)系列將使用當(dāng)下比較流行的 Hybrid APP 框架來(lái)實(shí)現(xiàn)一個(gè)總體的處理流程。