Android通用業務彈窗管理方案PopLayerV2

lalala同學發表於2019-02-14

前言

上回講到了 業務彈窗管理的Dialog形式 有興趣的同學 可以點選這裡去往上一篇文章瞭解回顧一下

這回的PoplayerV2版本是在此前Dialog基礎上擴充了一部分同學關心的透明Webview彈窗實踐效果

春節幾天假期加上上班休息的時間一點點的碼總算跟上計劃的進度了

這裡是此專案的Github地址,

所有庫和DEMO均已開源,需要的可以看看,別忘了點個Star哦,謝謝!!!

好了,接下來開始進入正題

本文著重介紹於 透明webview的彈窗效果與管理

讓我們來看看Dialog和WebView同時應用於我們的彈窗管理方案會迸發出怎麼樣的花火吧!

Webview策略擴充

在專案開始之初就已經打算 將類不同但在意義上為彈窗的對應不同的策略進行擴充套件,

Webview在Poplayer中的擴充套件形式為WebViewLayerStrategyImpl,

關於Webview的內容很多,多到足夠寫成一份單獨的文章了 關於webview的配置,一些前任跨過的深坑,如何設計一個優雅健壯的androidWebview 這裡可以推薦大家看

基於考拉電商平臺的WebView實踐

分析的很全面 在實現時考慮的方面很廣 看完之後收益匪淺的一篇博文

再說框架本身, Poplayer內建對Webview的支援 並且對Webview進行了一系列配置 包括 Websetting Chromeclient Webclient 當然使用者可以自定義這些配置已滿足其獨特的業務功能,這裡推薦使用者實現自定義配置時 繼承Poplayer內建的配置元件 已滿足Poplayer的功能運轉

當然,單單的webview支援是不足以滿足我們繁雜的業務的

Poplayer為您提供了多種Webview策略下的功能擴充:

1.統一Webview情形下的觸控監聽

如下圖 全屏透明webview總是存在web控制元件和原生控制元件的異同

Android通用業務彈窗管理方案PopLayerV2

Poplayer 將其劃分為內部區域與外部區域(實體與空心) 能統一大部分的彈窗觸控反饋, 使用者可以實現此介面來自定義不同種類彈窗的觸控之後的效果

/**
 *  彈窗的觸控機制 統一  分為實體區域 和 外圍區域 觸控時的事件收發可以自定義
 */
public interface LayerTouchSystem {
    //觸控到外部區域
    void onTouchOutSideArea(IPop iPop);
    //觸控到內部區域
    void onTouchSolidArea(IPop iPop);
}
複製程式碼

Poplayer已經預設實現了Webview彈窗種類下的觸控效果

通常情況下全屏Webview會攔截觸控事件 對於彈窗來說他只需一小部分為其觸控區域 其他區域的點選需要下發事件到Native,下面是觸控事件的簡單分析

觸控事件分析

這裡關鍵點在於onTouchEvent的處理 Webview本身是攔截事件的 為此我們需要一個標識-什麼時候需要攔截?

這裡貼上Poplayer是如何處理的

 @Override
    public boolean onTouch(View v, MotionEvent event) {
    
        int alpha=0;
        //每一次觸控生成bitmap
        Bitmap bitmap= PopUtils.getBitmapFromView(this);
        //獲取觸控點的ARGB的alpha值 將點陣圖回收
        if (null != bitmap) {
            int pixel = bitmap.getPixel((int)event.getX(), (int)event.getY());
            alpha = Color.alpha(pixel);
            bitmap.recycle();
        }

        if(alpha==255){//實體
            layerTouchSystemImpl.onTouchSolidArea(this);
        }else {
            layerTouchSystemImpl.onTouchOutSideArea(this);
        }
        return false;
    }
複製程式碼

首先設定onTouchListenr的監聽

每一次觸控時我會生成當前點選畫素的點陣圖拿到當前點選的點的透明度

之後回收點陣圖 根據透明度呼叫事先設定的回撥即可

事件分發到onTouchEvent即可根據回撥的狀態 設定攔截還是分發事件給native

PS: 考慮到業務場景的不同 定製程度比較高的應用 建議實現屬於自己的擴充套件

(這裡存在的問題是動態特效彈窗詳情下,觸控會出現卡頓,各位大佬如果有更好的方案,請在評論區留下您寶貴的建議)

2.預設內建JS原生互動方式

/**
 * 混合開發管理 使用者可自定義
 */
public interface HybirdManager {

    //注入JSBridge 時機在onreceivetitle
    void injectJsBridge(WebView webView,String jsName);

    //呼叫本地提供的基礎服務 時機 1.jsprompt 2.post請求 3.原生 4.shouldOverrideUrlLoading
    void invokeAppServices(String instruction) ;

    //加入JS中android本地物件 時機webview初始化
    void addUpJavaNativeJSInterface(WebView webView, String windowObjName);

}
複製程式碼

對於Webview彈窗來說與JS的互動是不可缺少的,市面上有許多與JS互動的框架,Android同樣有著原生支援,Poplayer支援使用者自定義與彈窗互動的方式,也同樣提供了基於JSBridge和原生的預設互動實現,可根據業務與喜好擇一使用

這裡為了說明方便將下文的互動概念稍微統一

原生調H5為提供基礎擴充套件,同理H5調原生為呼叫基礎服務

Poplayer中提供了預設的基礎服務元件 PopWebViewService

主要包含彈窗 顯示和消失等基本功能 和適合各個專案的統一路由服務

當網頁顯示的時候 我們可以在web偵錯程式console中看到DOM物件的屬性

Android通用業務彈窗管理方案PopLayerV2

PS: 這裡的路由 JS傳的是呼叫客戶端服務的基礎協議 這個協議由jsbridge內部形成 類似結構router://type=xxx?value=yyy,是由使用者根據其業務決定的

內建JSbridge

框架中已經內建了Jsbridge,這裡就不貼出程式碼一一說明了

簡單的放一張原理圖闡述雙端的互動機制

JSBridge

注入時機

Poplayer在這裡採取在載入完頭部標題時注入的機制

 @Override
    public void onReceivedTitle(WebView view, String title) {
        //注入JSBridge的時機
        if(mHybirdImpl!=null){
            mHybirdImpl.injectJsBridge(view,jsBridgeName);
        }
        super.onReceivedTitle(view, title);
    }
複製程式碼

根據考拉團隊的做法

通過設定載入閾值 在監聽WebViewClient.onProgressChanged()函式時根據進度來注入也是可行的

回撥服務時機

考慮到現今WebView的回撥特點, Poplayer儘可能全面的在四種方案回撥了基礎服務介面 並在下面分析了各自的優缺點,使用者可擇其使用

1.JsPrompt

侵入WebChromeClient.onJsPrompt(webview, url, message, defaultValue, result)實現通訊。

優點 返回值型別多樣 訊息長度上限高

缺點 可能需要處理彈窗問題

2.攔截JS Post請求

優點 通過請求來做操作 可以進行鑑權加密 提高安全性

缺點 請求體body裡的內容android端無法接收到(IOS是可以拿到的)

3.Native函式也接收回撥

優點 使用方便 管理方便

缺點 容易被反編譯破解 拿到服務資訊

4.ShouldOverrideUrlLoading攔截跳轉

優點 前端用方便 location.href即可

缺點 有些機型此函式是無法生效的

最終回撥服務都通往HybirdManager介面的invokeAppServices函式,回收到命令字串

 public void invokeAppServices(String instruction) {
         //收到字串格式的命令分為兩種型別1.路由
        Uri uri=Uri.parse(instruction);
        if(uri.getscheme().equals(routerScheme)){
            doRouter(instruction);
        }else{
        //2.jsbridge中取出的 函式體呼叫式JSON
        //類似{"invokeId":"name_2_1549953808581","methodName":"name","methodParams":"123"}
        //此函式需要解析此json呼叫基礎服務物件的對應方法
        doInvokePopWebviewService(instruction);
       }
    
 }
複製程式碼

3.配置了彈窗管理Callback 方便使用者監聽彈窗管理過程

public interface PopCallback {

    //彈窗已經存在於佇列中
    void onPopExisted(int queueSize);

    //彈窗不在活動時間內
    void onPopOutOfDate();

    //彈窗已經顯示了最大個數
    void onPopShowMaxCount();

    //彈窗顯示成功回撥
    void onPopShowSuccess();

    //彈窗延遲消失回撥
    void onPopDelayDismiss();

}
複製程式碼

彈窗效果預覽

彈窗效果預覽

JS互動效果預覽

因為是手機錄的屏 依次按順序傳送命令 最終回撥invokeService裡顯示彈窗

JS互動效果預覽

特效展示(紅包雨)

特效展示(紅包雨)

關於專案

POPLAYER

一個通用的Android端彈窗管理框架,內部維護彈窗優先順序佇列 具備彈窗管理擴充套件功能 整合Dialog,PoupoWindow,懸浮Widget,透明Webview,Toast,SnackBar,無需再為繁瑣的業務彈窗邏輯所困擾

具體如何使用 可以去github.com/MrCodeSnipe…閱讀下面的使用說明文件

您也可以下載Demo體驗一番 如有問題 可以在Github上開啟Issue或在簡書評論或者私密

V1方案

版本號 LOG 進度更新
V1.0.0 專案開源,完成彈窗管理與Dialog形式擴充套件 Dialog策略擴充套件完成
V1.0.1 修復Dialog策略無法獲取dialog實體bug Dialog策略優化
V1.0.2 修復activity摧毀造成的彈窗異常 bug Dialog策略優化
V1.0.3 優化了彈窗的使用更加方便快捷 框架使用優化

V2方案

版本號 LOG 進度更新
V2.0.0 正式加入透明Webview彈窗策略擴充套件 透明Webview策略擴充套件完成

接下來的計劃

結束了Webview的擴充套件 後期會對框架進行進一步優化

包括JSBridge功能的封裝,更加靈活的配置Webview等 也請感興趣的同學 給我些建議

新的一年也請多多指教!!!

其他型別的彈窗也會陸續更新 希望能提供給大家一個較為全面的應對各種業務需求的彈窗管理框架


Hello 我叫lalala,如果您喜歡我的文章,可以去我的Github給個Star我就很開心啦!!!

Github:github.com/MrCodeSnipe…

--End

相關文章