當(dāng)下主流 APP , Hybrid app 中需要熟練掌握的交互知識(shí)(二)

如果感覺(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è)總體的處理流程。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,323評(píng)論 25 708
  • 2014年10月29日,萬(wàn)維網(wǎng)聯(lián)盟宣布,經(jīng)過(guò)接近8年的艱苦努力,該標(biāo)準(zhǔn)(HTML5)規(guī)范終于制定完成。接著,整個(gè)移...
    smartbeng閱讀 2,463評(píng)論 0 20
  • ¥開(kāi)啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開(kāi)一個(gè)線程,因...
    小菜c閱讀 7,380評(píng)論 0 17
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,631評(píng)論 4 61
  • 對(duì)不起,我只是個(gè)小孩,我只想做個(gè)健康,快樂(lè)的孩子。 不想接受歧視的眼光與朋友的嘲笑。 希望你能給我多點(diǎn)溫暖,像太陽(yáng)...
    王冊(cè)3閱讀 730評(píng)論 2 1

友情鏈接更多精彩內(nèi)容