簡單封裝一個易拓展的Dialog
本文正在參加「金石計劃 . 瓜分6萬現金大獎」
Dialog,每個專案中多多少少都會用到,肯定也會有自己的一套封裝邏輯,無論如何封裝,都是奔著簡單複用的思想,有的是深層次的封裝,也就是把相關的UI效果直接封裝好,暴露可以修改的屬性和方法,讓呼叫者根據實際業務,呼叫修改即可,當然也有簡單的封裝,只封裝基本的功能,其UI和實際的動作,交給呼叫者,兩種封裝方式,各有利弊,前者呼叫者不用自己建立UI和實現相關動作,只需要簡單的呼叫即可,但是不易於擴充套件,效果比較侷限,想要拓展其他的效果,就不得不自己動手實現;後者擴充套件性強,因為只提供基本的呼叫方式,也就是說,你想要什麼效果都行,畢竟是所有的UI和動作都是你自己來實現,優點是它,其缺點也是它。
前者的封裝司空見慣,大多數的公司也都是採取的這樣的封裝,畢竟呼叫者實現起來也是很方便,這裡就不詳細說了,具體我們談一下後者的封裝,後者的封裝雖然呼叫者需要自己來實現,但是擴充套件性是很強的。
今天的內容大致如下:
1、效果及程式碼具體呼叫。
2、如何封裝一個Dialog。
3、開源地址。
4、總結及注意事項。
一、效果及程式碼具體呼叫
通過Kotlin的擴充套件函式,引數以類做為擴充套件,封裝之後,呼叫非常的便捷,只需要傳遞你要的檢視即可,我們先看下具體的案例,程式碼如下:
kotlin
showVipDialog {
addLayout(R.layout.layout_dialog_custom)//傳遞dialog檢視
set {
//Dialog操作,獲取View及繫結資料
}
}
通過以上的程式碼,我們就實現了一個Dialog的彈出,addLayout方法傳遞檢視,set擴充套件函式進行獲取View和繫結資料,這樣的一個簡單的封裝,我們就實現了Dialog的擴充套件操作,針對不同的Dialog樣式,傳遞不同的xml檢視即可。
1、快速使用
為了方便大家使用,目前已經上傳到了遠端maven,大家可以進行依賴使用,或者下載原始碼依賴也可以。
根專案build.gradle
allprojects {
repositories {
……
maven { url "https://gitee.com/AbnerAndroid/almighty/raw/master" }
}
}
在需要的Module下引入依賴
dependencies {
……
implementation "com.vip:dialog:1.0.0"
}
2、程式碼案例
原始碼下載之後,執行專案,就可以看到給大家提供的相關Demo,當然了,由於做到了可擴充套件,大家想實現什麼樣的效果都是可以的,畢竟檢視都是自己傳遞的。
由於所有的案例都是呼叫開頭的程式碼,就不一一列舉了,簡單的列舉幾個。
普通的提示框
普通的提示框,可以按照下面的程式碼邏輯進行呼叫。
kotlin
showVipDialog {
addLayout(R.layout.layout_dialog_custom)//新增彈出的檢視
set {//邏輯處理,獲取view,繫結資料
setDialogCancelable(false)//點選空白不消失
val btnConfirm = findView<TextView>(R.id.dialog_button_confirm)//獲取View
btnConfirm.setOnClickListener {
toast("確定")
dismiss()
}
}
}
方法一覽
| 方法名 | 引數型別 | 概述 | | ------------------- | ------- | --------------------------- | | addLayout | int | xml檢視 | | set | 無參 | 邏輯處理 | | style | 無參 | dialog設定樣式 | | setDialogCancelable | Boolean | 點選空白是否消失,預設true消失,false為不消失 | | findView | int | 控制元件id,泛型為控制元件 | | dismiss | 無參 | 隱藏dialog | | getDialogView | 無參 | 獲取當前View檢視 |
DataBinding形式的提示框
DataBinding形式和普通的區別在於,不用再獲取View檢視,由普通的set擴充套件函式改為bind擴充套件函式,泛型為Binding,記得把xml檢視進行convert to data binding layout。
kotlin
showVipDialog {
addLayout(R.layout.layout_dialog_custom)//新增彈出的檢視
bind<LayoutDialogCustomBinding> {//邏輯處理,獲取view,繫結資料
it.dialogButtonConfirm.setOnClickListener {
toast("確定")
dismiss()
}
}
}
方法一覽
除了普通的方法呼叫之外,還可以呼叫下面的方法。
| 方法名 | 引數型別 | 概述 | | ------------------ | --- | ------------------------------- | | bind | 無參 | 和set一樣進行邏輯處理,泛型為ViewDataBinding | | getDataBinding | 無參 | 獲取當前的DataBinding,用於更新檢視 | | setPendingBindings | int | 傳遞的BR,用於xml和Data資料進行繫結 |
具體的案例大家直接可以看原始碼,原始碼中提供了很多常見的效果,都是可以自定義實現的,具體的就不羅列了,本身沒有多少難度。
確認框
輸入框
底部列表
菊花載入
二、如何封裝一個Dialog
這樣的一個簡單的Dialog如何進行封裝呢?在封裝之前,我們首先要明確封裝思路,1、檢視由呼叫者傳遞,2、邏輯操作由呼叫者處理,3、樣式也由呼叫者進行設定,也就是說,我們只封裝基本的dialog使用,也就是一個殼,具體的內容,統統交給呼叫者進行處理,有了這三個思路我們就可以進行著手封裝了。
1、封裝BaseDialog
封裝Base的原因,在於統一管理子類,在於簡化子類的程式碼邏輯,便於提供公共的方法讓子類實現或呼叫,BaseDialog這裡繼承的是DialogFragment,最大的原因就是,容易通過生命週期回撥來管理彈窗,還有對於複雜樣式的彈窗,使用DialogFragment會更加方便和高效。
和之前封裝Activity一樣,做為一個抽象父類,子類要實現的無非就是,檢視的傳遞和邏輯的處理,我們就可以在父類中進行定義抽象方法,Dialog一般有自己定義的樣式,我們也可以定義一個初始化樣式的方法。
```kotlin /* * AUTHOR:AbnerMing * INTRODUCE:初始化資料 / abstract fun initData()
/**
* AUTHOR:AbnerMing
* INTRODUCE:初始化樣式
*/
abstract fun initStyle()
/**
* AUTHOR:AbnerMing
* INTRODUCE:傳遞的檢視
*/
abstract fun getLayoutId(): Int
```
除了必要實現的方法之外,我們還可以把一些公用的方法,定義到Base裡,如獲取View的方法,獲取控制元件的方法等,這麼做的目的,便於子類自定義實現一些效果以及減少findViewById的呼叫次數。
```kotlin
/*
* AUTHOR:AbnerMing
* INTRODUCE:獲取View檢視
/
fun
/**
* AUTHOR:AbnerMing
* INTRODUCE:獲取當前View檢視
*/
fun getDialogView(): View {
return mView!!
}
```
以上只是列舉了幾個實現的方法,完整的程式碼,大家可以看原始碼中的BaseDialog類。
2、拓展ViewDataBinding形式Dialog
正常的普通Dialog就可以繼承BaseDialog,基本就可以滿足需要的,若是要和ViewDataBinding進行結合,那麼就需要拓展需求了,具體的拓展也很簡單,一是繫結View,二是繫結資料,完整的程式碼,大家可以看原始碼中BaseBindingDialog類。
繫結View
通過DataBindingUtil的bind方法,得到ViewDataBinding。
kotlin
mBinding = DataBindingUtil.bind(getDialogView())
繫結資料
完成xml檢視和資料的繫結。
kotlin
mBinding.setVariable(variableId, t)
mBinding.executePendingBindings()
3、封裝工具類,拓展相關功能
為了更加方便的讓呼叫者使用,封裝拓展函式是很有必要的,要不然,呼叫者每次都得要繼承上邊的兩個父類,這樣的程式碼就會增加很多,還會建立很多的類,我們需要單獨的建立一個工具類,來例項化我們需要簡化的功能邏輯。
提供新增xml檢視的方法
很簡單的一個普通方法,沒什麼好說的,把傳遞的xml,賦值給重寫的getLayoutId方法即可。
kotlin
/**
* AUTHOR:AbnerMing
* INTRODUCE:設定layout
* @param mLayoutId xml佈局
*/
fun addLayout(mLayoutId: Int): VipDialog {
this.mLayoutId = mLayoutId
return this
}
提供普通使用和DataBinding形式使用方法
普通和DataBinding方法,這裡用到了介面回撥,介面的實現則在initVMData方法裡,兩個方法本身功能是一樣的,無非就是一個是普通,一個是返回ViewDataBinding。
```kotlin
/*
* AUTHOR:AbnerMing
* INTRODUCE:初始化資料
/
fun
/**
* AUTHOR:AbnerMing
* INTRODUCE:初始化資料
*/
fun set(block: () -> Unit): VipDialog {
setDataCallBackListener(object : OnDialogDataCallbackListener {
override fun dataCallback() {
block.invoke()
}
})
return this
}
```
提供設定樣式的方法
樣式的設定也就是使用了介面回撥。
kotlin
/**
* AUTHOR:AbnerMing
* INTRODUCE:設定樣式
*/
fun style(style: () -> Unit): VipDialog {
setStyleCallBackListener(object : OnStyleCallBackListener {
override fun styleCallback() {
style.invoke()
}
})
return this
}
提供獲取ViewDataBinding的方法
這個方法的提供是便於拿到ViewDataBinding,有效的更新檢視資料。
kotlin
/**
* AUTHOR:AbnerMing
* INTRODUCE:獲取ViewDataBinding
*/
fun <VB : ViewDataBinding> getDataBinding(): VB {
return mBinding as VB
}
我們看下整體的程式碼,如下:
```kotlin
/
AUTHOR:AbnerMing
DATE:2022/11/22
INTRODUCE:例項化功能
/
class VipDialog : BaseBindingDialog
companion object {
fun init(): VipDialog {
return VipDialog()
}
}
private var mLayoutId = 0
override fun initVMData() {
mOnDialogDataCallbackListener?.dataCallback()
}
override fun initStyle() {
mOnStyleCallBackListener?.styleCallback()
}
override fun getLayoutId(): Int {
return mLayoutId
}
/**
* AUTHOR:AbnerMing
* INTRODUCE:獲取ViewDataBinding
*/
fun <VB : ViewDataBinding> getDataBinding(): VB {
return mBinding as VB
}
/**
* AUTHOR:AbnerMing
* INTRODUCE:設定layout
* @param mLayoutId xml佈局
*/
fun addLayout(mLayoutId: Int): VipDialog {
this.mLayoutId = mLayoutId
return this
}
/**
* AUTHOR:AbnerMing
* INTRODUCE:初始化資料
*/
fun <VB : ViewDataBinding> bind(block: (bind: VB) -> Unit): VipDialog {
setDataCallBackListener(object : OnDialogDataCallbackListener {
override fun dataCallback() {
block.invoke(getDataBinding())
}
})
return this
}
/**
* AUTHOR:AbnerMing
* INTRODUCE:初始化資料
*/
fun set(block: () -> Unit): VipDialog {
setDataCallBackListener(object : OnDialogDataCallbackListener {
override fun dataCallback() {
block.invoke()
}
})
return this
}
/**
* AUTHOR:AbnerMing
* INTRODUCE:設定樣式
*/
fun style(style: () -> Unit): VipDialog {
setStyleCallBackListener(object : OnStyleCallBackListener {
override fun styleCallback() {
style.invoke()
}
})
return this
}
private var mOnDialogDataCallbackListener: OnDialogDataCallbackListener? = null
private fun setDataCallBackListener(mOnDialogDataCallbackListener: OnDialogDataCallbackListener) {
this.mOnDialogDataCallbackListener = mOnDialogDataCallbackListener
}
private var mOnStyleCallBackListener: OnStyleCallBackListener? = null
private fun setStyleCallBackListener(mOnStyleCallBackListener: OnStyleCallBackListener) {
this.mOnStyleCallBackListener = mOnStyleCallBackListener
}
} ```
4、封裝拓展函式,簡化呼叫
dialog的彈出可能有很多場景,比如Activity裡,比如Fragment裡,比如一個工具類中,我們可以根據已知的場景,來定義我們的呼叫方式,目前,我定義了兩種,在Activity或者Fragment裡可以直接進行呼叫,也就是開頭的呼叫方式,當然了,大家也可以自己拓展。
```kotlin /* * AUTHOR:AbnerMing * INTRODUCE:Activity顯示Dialog / fun AppCompatActivity.showVipDialog(vipDialog: VipDialog.() -> Unit): VipDialog { val dialog = VipDialog.init() dialog.apply(vipDialog) setActivityDialog(this.supportFragmentManager, dialog) return dialog }
/* * AUTHOR:AbnerMing * INTRODUCE:Fragment顯示Dialog / fun Fragment.showVipDialog(vipDialog: VipDialog.() -> Unit): VipDialog { val dialog = VipDialog.init() dialog.apply(vipDialog) setActivityDialog(this.childFragmentManager, dialog) return dialog } ```
通過以上幾步,我們就可以實現開頭的簡單呼叫,具體的大家可以檢視相關原始碼。
三、開源地址
專案地址:https://github.com/AbnerMing888/VipDialog
四、總結及注意事項
在開頭已經闡述,這種方式易於拓展,但是程式碼量相對比較多,畢竟所有的UI和邏輯都必須獨自來處理,在專案中的解決方式為,如果很多的彈框效果一樣,建議再封裝一層,抽取公共的工具類。
還有一個需要注意的,本身擴充套件函式showVipDialog返回的就是呼叫的類,也就是一個Dialog,大家可以直接獲取變數,在其他的地方做更新Dialog或者銷燬的操作。
kotlin
val dialog=showVipDialog {
……
}
- Android自動生成程式碼,視覺化腳手架之基礎資訊配置
- 如何搞一個線上的Shape生成
- 簡單封裝一個易拓展的Dialog
- 整合一個以官網(微信,QQ,微博)為標準的登入分享功能
- Android打造專有Hook第四篇,實戰增量程式碼規範檢查
- Android極簡MVVM,從一個基類庫談起
- Android元件化開發,其實就這麼簡單
- Android打造專有hook,讓不規範的程式碼扼殺在萌芽之中
- Android包體積過大,真的會影響績效
- Android長按圖示展示快捷方式
- Android自動生成Shape資原始檔(下)
- Android自動生成Shape資原始檔,邁出視覺化腳手架第一步!(上)
- Android自動生成程式碼,視覺化腳手架,將大大提高開發效率
- Android自動生成程式碼,視覺化腳手架之環境搭建
- 怎麼去約束程式碼的統一性
- 沒有準備充分,先不要著急投簡歷
- Android如何生成本地或者遠端aar