[Android開源框架]AnyLayer使用說明

AnyLayer

Android穩定高效的浮層創建管理框架。

可取代系統自帶Dialog/Popup/BottomSheet等彈窗,可實現單Activity架構的Toast提示,可定制任意樣式的Guide引導層,可實現依附Activity的Float懸浮按鈕。

GitHub主頁

Demo下載

簡介

  • 同時兼容support和androidx
  • 鏈式調用
  • 支持自由擴展
  • 實現幾種常用效果
    • Dialog效果
      • 占用區域不會超過當前Activity避免導航欄遮擋
      • 支持自定義大小和顯示位置
      • 支持自定義數據綁定
      • 支持自定義進出場動畫
      • 支持自定義背景顏色/圖片/高斯模糊
      • 支持在Activity的onCreate生命周期彈出
      • 支持從ApplicationContext中彈出
    • Popup效果
      • 擁有Dialog效果特性
      • 支持跟隨目標View移動
    • Toast效果
      • 支持自定義圖標和文字
      • 支持自定義顯示時長
      • 支持自定義位置
      • 支持自定義背景資源和顏色
      • 支持自定義透明度
      • 支持自定義進出場動畫
    • Guide效果
      • 引導層效果待開發
    • Float效果
      • 懸浮按鈕效果待開發

說明

詳細原理和使用說明本人會在后續補上,但因個人開發,時間不定,請諒解。

或有大佬在看過源碼后,愿意寫下分析文章或使用說明來分享的,歡迎聯系本人。寫得比較詳細的本人將會放到README中供大家查閱,提前謝過。

當然也歡迎加群共同探討,共同進步。

QQ群:147715512(愛Android)

使用該庫的產品

如果你的產品正在使用AnyLayer,歡迎留下相關信息

這些信息將用來幫助更多開發者關注并使用本框架,增加框架的活躍度。而高活躍度則意味著更多隱藏BUG被發現并修復,即活躍度等同于框架的健壯性。同時這也是我維護項目的最大動力,感謝。

APP名 APP圖標 公司名
玩安卓
個人
熊貓淘學
西安熊貓寶寶網絡科技有限公司
MBA大師
MBA大師

截圖

截圖效果較差且版本較老,建議下載Demo體驗最新功能

使用說明

集成

  • 添加jitpack庫

// build.gradle(Project:)
allprojects {
    repositories {
        ...
            maven { url 'https://www.jitpack.io' }
    }
}
  • 添加依賴

    點擊查看最新版本號

    引用時需注意版本號,從2.3.1版本開始,版本號前不加v。

    通用庫為在2.4.0版本新增,有效引用為2.4.0~2.5.0之間版本。

    從3.0.0版本開始,框架重構,刪除通用庫。因重構代碼變化較大,不建議使用較多的老項目升級,保持2.5.0版即可,在實現Dialog/Popup等效果上無本質差別。

    從3.1.0版本開始移除對support-v7的依賴,可同時兼容support和androidx

// build.gradle(Module:)
dependencies {
    // 完整引入
    implementation 'com.github.goweii:AnyLayer:3.2.0'
    
    // 基礎庫
    // implementation 'com.github.goweii.AnyLayer:anylayer:2.5.0'
    
    // 通用彈窗(依賴基礎庫)
    // 從3.0.0版本暫時刪除
    // implementation 'com.github.goweii.AnyLayer:anylayer-common:2.5.0'
}

類間關系

  • AnyLayer(提供常用效果的調用入口)

  • ViewManager(管理View的動態添加移除和KeyEvent事件注冊)

  • Layer(對ViewManager的包裝,實現進出場動畫邏輯和事件監聽,規范接口形式,分離出ViewHolder/ListenerHolder/Config三大內部類)

    • DecorLayer(規范父布局為DecorView的特殊Layer,引入了Layer層級概念)
      • DialogLayer(規范子布局層級,加入背景層,分離動畫為背景動畫和內容動畫)
      • ToastLayer(定時消失,不響應事件的Layer)
      • GuideLayer(引導層Layer)
      • FloatLayer(懸浮按鈕Layer)
  • AnimatorHelper(創建常用屬性動畫)

類說明

AnyLayer

一個工廠效果的工具類,與Layer類族的關系就像Executors于Executor的關系這樣。

只是提供了靜態方法方便調用,不用new來new去的。

/**
 * 初始化高斯模糊,可在用到高斯模糊背景的Activity的onCreate方法調用
 * 其實不調用也沒關系,第一次顯示的時候也會初始化的,只是這樣第一次顯示就會比后面顯示稍微慢一點
 */
public static void initBlurred(Context context)

/**
 * 回收高斯模糊內存占用,可在用到高斯模糊背景的Activity的onDestroy方法調用,也可以在內存不足時調用
 */
public static void recycleBlurred()

/**
 * 創建一個DialogLayer
 * 這個Context不能是ApplicationContext
 */
public static DialogLayer dialog(Context context)

/**
 * 創建一個DialogLayer
 * 依附的是當前顯示的Activity
 */
public static DialogLayer dialog()

/**
 * 創建一個DialogLayer
 * 依附的是特定Class的Activity實例,這個Activity必須是已經啟動的
 */
public static DialogLayer dialog(Class<Activity> clazz)

/**
 * 創建一個DialogLayer
 * 會啟動一個新的全透明Activity依附
 */
public static void dialog(LayerActivity.OnLayerCreatedCallback callback)

/**
 * 創建一個PopupLayer
 */
public static PopupLayer popup(View targetView)

/**
 * 創建一個ToastLayer
 * 依附的是當前顯示的Activity
 */
public static ToastLayer toast()

/**
 * 創建一個ToastLayer
 * 這個Context不能是ApplicationContext
 */
public static ToastLayer toast(Context context)

ViewManager

這個就不介紹了吧?一般用的時候也用不到,后面原理剖析的時候再說吧!

Layer

上面類間關系簡單描述了一下

對ViewManager的包裝,實現進出場動畫邏輯和事件監聽,規范接口形式,分離出ViewHolder/ListenerHolder/Config三大內部類

可以看出這個類是所有效果的基類,有以下幾個特定:

  • 對ViewManager的包裝

    可以自由指定父布局和子布局,可以通過繼承在onGetParent和onCreateChild中返回,也可以通過parent()和child()方法設置。

    其次是幾個生命周期回調方法

    • onAttach(View剛被添加到父布局)
    • onPreDraw(View開始繪制前,這里開始執行進場動畫)
    • onShow(View顯示,進場動畫結束)
    • onPreRemove(View準備移除時,這里開始執行出場動畫)
    • onDetach(View已被移除,出場動畫結束)
  • 實現進出場動畫邏輯

    在onPreDraw和onPreRemove中實現了進出場動畫的流程。可通過繼承在onCreateInAnimator和onCreateOutAnimator中返回,也可以通過animator()方法設置。

    其中AnimatorCreator為創建自定義進出場動畫的接口

  • 事件監聽

    有幾個常用的事件監聽,在ListenerHolder中統一管理

    • DataBinder(綁定數據)
    • OnClickListener(點擊事件監聽)
    • OnShowListener(顯示動畫開始和結束監聽)
    • OnDismissListener(消失時動畫開始和結束監聽)
    • OnVisibleChangeListener(顯示隱藏狀態改變的監聽)
  • 分離出ViewHolder/ListenerHolder/Config三大內部類

    這個看名字應該就知道了,就不介紹了。

  • 常用方法

    /**
     * 一組控制顯示隱藏的方法
     */
    public void show()
    public void show(boolean withAnim)
    public void dismiss()
    public void dismiss(boolean withAnim)
        
    /**
     * 判斷當前顯示隱藏狀態
     */  
    public boolean isShow()
        
    /**
     * 根據ID獲取對應View
     */  
    public <V extends View> V getView(int id)
        
    /**
     * 指定父布局
     */  
    public Layer parent(ViewGroup parent)
        
    /**
     * 指定子布局
     */  
    public Layer child(View child)
        
    /**
     * 自定義進出場動畫
     */  
    public Layer animator(AnimatorCreator creator)
    
    /**
     * 是否攔截物理按鍵,為true時cancelableOnKeyBack才有效
     */  
    public Layer interceptKeyEvent(boolean intercept)
        
    /**
     * 是否可點擊返回鍵關閉浮層,interceptKeyEvent為true才有效
     */  
    public Layer cancelableOnKeyBack(boolean cancelable)
        
    /**
     * 一組事件監聽,見上面介紹
     */  
    public Layer bindData(DataBinder dataBinder)
    public Layer onVisibleChangeListener(OnVisibleChangeListener onVisibleChangeListener)
    public Layer onShowListener(OnShowListener onShowListener)
    public Layer onDismissListener(OnDismissListener onDismissListener)
        
    /**
     * 點擊某些控件關閉浮層
     */  
    public Layer onClickToDismiss(OnClickListener listener, int... viewIds)
    public Layer onClickToDismiss(int... viewIds)
        
    /**
     * 對控件綁定點擊事件
     */  
    public Layer onClick(OnClickListener listener, int... viewIds)
    

DecorLayer

繼承自Layer,強制父布局為DecorView。主要就是引入了Layer層級概念。

而這個層級就是由兩個靜態內部類實現的

  • LayerLayout

    繼承自FrameLayout,是各個層級浮層的容器,直接添加進DecorView。

  • LevelLayout

    繼承自FrameLayout,定義了Level概念,是每個浮層的父布局,也就是在外面包了一層,用來控制浮層上下層級的容器。這個是直接添加進LayerLayout的。

好了就這么多了。更多了細節還是看源碼吧。

DialogLayer

這個就是模仿傳說中Dialog效果的浮層。用上面的描述就是:

規范子布局層級,加入背景層,分離動畫為背景動畫和內容動畫

一個一個來看。

  • 規范子布局層級,加入背景層

    從DecorLayer的介紹中可以知道LevelLayout是該類浮層的直接父布局。但它并不是DialogLayer中contentView的直接父布局。就是因為又加了一個ViewGroup把contextView和background包裹起來。布局文件是這樣子的。

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/fl_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clickable="true">
    
        <ImageView
            android:id="@+id/iv_background"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="centerCrop"/>
    
        <FrameLayout
            android:id="@+id/fl_content_wrapper"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    
    </FrameLayout>
    

    contentView其實是直接添加至fl_content_wrapper中的。

  • 分離動畫為背景動畫和內容動畫

    因為有了contextView和background的概念,原來的動畫就不好用了。所以從寫了動畫的創建邏輯,分離了背景和前景應用不同的動畫。

最后看下常用的方法。

/**
 * 設置自定義布局View/資源ID
 */
public DialogLayer contentView(View contentView)
public DialogLayer contentView(int contentViewId)

/**
 * 設置自定義布局文件中狀態欄的占位View
 * 該控件高度將設置為狀態欄高度,可用來使布局整體下移,避免狀態欄遮擋
 */
public DialogLayer asStatusBar(int statusBarId)

/**
 * 設置避開狀態欄
 */
public DialogLayer avoidStatusBar(boolean avoid)

/**
 * 設置子布局的gravity
 * 可直接在布局文件指定layout_gravity屬性,作用相同
 */
public DialogLayer gravity(int gravity)

/**
 * 自定義浮層的進入和退出動畫
 */
public DialogLayer contentAnimator(AnimatorCreator contentAnimatorCreator)

/**
 * 自定義背景的進入和退出動畫
 */
public DialogLayer backgroundAnimator(AnimatorCreator backgroundAnimatorCreator)

/**
 * 設置背景高斯模糊/圖片/顏色
 */
public DialogLayer backgroundBlurRadius(float radius)
public DialogLayer backgroundBlurPercent(float percent)
public DialogLayer backgroundBlurScale(float scale)
public DialogLayer backgroundBitmap(Bitmap bitmap)
public DialogLayer backgroundDimAmount(float dimAmount)
public DialogLayer backgroundResource(int resource)
public DialogLayer backgroundDrawable(Drawable drawable)
public DialogLayer backgroundColorInt(int colorInt)
public DialogLayer backgroundColorRes(int colorRes)

/**
 * 設置點擊浮層以外區域是否可關閉
 */
public DialogLayer cancelableOnTouchOutside(boolean cancelable)

/**
 * 設置點擊返回鍵是否可關閉
 */
public DialogLayer cancelableOnClickKeyBack(boolean cancelable)

算了,再看下調用代碼湊湊字數把。

AnyLayer.dialog(this)
        .contentView(R.layout.dialog_test_2)
        .backgroundColorRes(R.color.dialog_bg)
        .gravity(Gravity.CENTER)
        .cancelableOnTouchOutside(true)
        .cancelableOnClickKeyBack(true)
        .bindData(new Layer.DataBinder() {
            @Override
            public void bindData(Layer layer) {
                // TODO 綁定數據
            }
        })
        .onClickToDismiss(R.id.fl_dialog_no)
        .show();

PopupLayer

因為繼承自DialogLayer,所以可以使用定義過的方法(這不是廢話嗎)。

主要就是加入了可依據錨點View定位。

這個效果可能還要重構,暫時就不介紹了。

看下其他新增方法。

/**
 * 設置浮層外部是否攔截觸摸
 * 默認為true,false則事件有activityContent本身消費
 */
public PopupLayer outsideInterceptTouchEvent(boolean intercept)

/**
 * 是否裁剪contentView至包裹邊界
 */
public PopupLayer contentClip(boolean clip)

/**
 * 是否偏移背景對齊目標控件
 */
public PopupLayer backgroundAlign(boolean align)

/**
 * 背景應用offset設置
 */
public PopupLayer backgroundOffset(boolean offset)

/**
 * 當以target方式創建時為參照View位置顯示
 * 可自己指定浮層相對于參照View的對齊方式
 */
public PopupLayer align(Align.Direction direction,
                        Align.Horizontal horizontal,
                        Align.Vertical vertical,
                        boolean inside)

/**
 * 指定浮層相對于參照View的對齊方式
 */
public PopupLayer direction(Align.Direction direction)

/**
 * 指定浮層相對于參照View的對齊方式
 */
public PopupLayer horizontal(Align.Horizontal horizontal)

/**
 * 指定浮層相對于參照View的對齊方式
 */
public PopupLayer vertical(Align.Vertical vertical)

/**
 * 指定浮層是否強制位于屏幕內部
 */
public PopupLayer inside(boolean inside)

/**
 * X軸偏移
 */
public PopupLayer offsetX(float offsetX, int unit)
public PopupLayer offsetXdp(float dp)
public PopupLayer offsetXpx(float px)
/**
 * Y軸偏移
 */
public PopupLayer offsetY(float offsetY, int unit)
public PopupLayer offsetYdp(float dp)
public PopupLayer offsetYpY(float px)

國際慣例,最后看下調用代碼湊湊字數。

AnyLayer.popup(targetView)
        .contentView(R.layout.dialog_test_4)
        .backgroundColorRes(R.color.dialog_bg)
        .direction(Align.Direction.VERTICAL)
        .horizontal(Align.Horizontal.CENTER)
        .vertical(Align.Vertical.BELOW)
        .inside(true)
        .contentAnim(new LayerManager.IAnim() {
            @Override
            public Animator inAnim(View content) {
                return AnimHelper.createTopInAnim(content);
            }

            @Override
            public Animator outAnim(View content) {
                return AnimHelper.createTopOutAnim(content);
            }
        })
        .show();

ToastLayer

累了,這個寫簡單點,就看下調用代碼算了。

AnyLayer.toast()
        .duration(3000)
        .icon(isSucc ? R.drawable.ic_success : R.drawable.ic_fail)
        .message(isSucc ? "哈哈,成功了" : "哎呀,失敗了")
        .show();

GuideLayer

待實現

FloatLayer

待實現

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,505評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,556評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,463評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,009評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,778評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,218評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,436評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,969評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,795評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,993評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,229評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,659評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,917評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,687評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,990評論 2 374

推薦閱讀更多精彩內容