GenjiDialog
基於kotlin的通用dialog
v1.1.2更新: kotlin版本升級到1.2.60,buildGradle版本升級到3.1.4,針對github中的issue修改了之前在AAA類繼承GenjiDialog時,重寫extendsOptions()的使用方式(ps:v1.1.1版本是個廢棄版本,不知道為什麼jitpack不編譯)
之前我是自己Fork了的一個叫NiceDialog的庫, 但是在這基礎上自己加了很多功能來自用,但是後來開始用kotlin開發之後, 發現很多東西都能簡化,畢竟kotlin的語法糖不能浪費了,所以就有了這個庫, 只要我還在做Android開發,應該會一直維護該庫。
專案地址:https://github.com/q876625596/GenjiDialogV2
依賴
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
複製程式碼
dependencies {
implementation 'com.github.q876625596:GenjiDialogV2:1.1.2'
}
複製程式碼
廢話不多說,直接上圖
內建大量基礎動畫,基本能滿足基本需求
第一次寫README也不知道該怎麼吹,就直接貼程式碼吧
newGenjiDialog {
width = dp2px(100f)
height = dp2px(100f)
}.showOnWindow(supportFragmentManager)
複製程式碼
就這麼簡單,一個預設居中的載入中loadDialog就出來了,如圖:
1、位置
如果我想讓他顯示在螢幕右上角怎麼辦?非常簡單!
newGenjiDialog {
width = dp2px(100f)
height = dp2px(100f)
gravity = DialogGravity.RIGHT_TOP
}.showOnWindow(supportFragmentManager)
複製程式碼
DialogGravity這個列舉中我設定了9種顯示方式,左上,中上,右上,左中,正中,右中,左下,中下,右下
因此只需要新增一行程式碼指定dialog的位置就行了、效果如圖:
你現在可能要問了,你只設定了9個位置,我需要偏移怎麼辦呢, 當然,這時候就需要用到偏移了
newGenjiDialog {
width = dp2px(100f)
height = dp2px(100f)
verticalMargin = dp2px(100f).toFloat()
horizontalMargin = dp2px(100f).toFloat()
gravity = DialogGravity.RIGHT_TOP
}.showOnWindow(supportFragmentManager)
複製程式碼
就這樣我就給dialog加上了橫向縱向分別100dp的偏移,效果如圖:
關於這個偏移量,這裡我多說兩句,原本偏移量的取值範圍是在[0-1],指的是所佔螢幕寬高的百分比, 但是為了方便起見,我這裡給大於1的偏移量自動換算成了百分比,如果針對個別機型有誤差的,可以自行換算成[0-1]即可
2、動畫
細心地你可能發現了,在螢幕右上角顯示的時候是從螢幕邊緣滑出的, 沒錯,我給DialogGravity的每一個顯示位置都設定了預設的動畫, 當沒有指定動畫的時候就會按照預設的動畫來顯示、
當然自定義動畫是肯定要有的
newGenjiDialog {
width = dp2px(100f)
height = dp2px(100f)
animStyle = R.style.ScaleADEnterExitAnimationX50Y50
gravity = DialogGravity.RIGHT_TOP
}.showOnWindow(supportFragmentManager)
複製程式碼
這樣就完成了動畫的自定義,當然你還可以這樣寫:
dialog.showOnWindow(supportFragmentManager,DialogGravity.RIGHT_TOP,R.style.ScaleADEnterExitAnimationX50Y50)
複製程式碼
效果如圖:
內建動畫我在style檔案中註釋寫了作用,可以自己去看看
如果想要貼在一個view附近怎麼辦?
newGenjiDialog {
width = dp2px(100f)
height = dp2px(100f)
animStyle = R.style.ScaleADEnterExitAnimationX50Y100
gravityAsView = DialogGravity.CENTER_TOP
}.showOnView(supportFragmentManager,showLoading)
複製程式碼
需要注意的是這裡的gravaty換成了gravityAsView,效果如圖:
同樣你還可以這樣寫:
dialog.showOnWindow(supportFragmentManager,DialogGravity.RIGHT_TOP,R.style.ScaleADEnterExitAnimationX50Y50)
複製程式碼
相對view的偏移量 offsetX和offsetY屬性
這兩個屬性建議去DialogOptions中的dialogAsView()方法去檢視方法註釋
附加一個稍微特殊點的滑出方式(帶遮罩)
newGenjiDialog { genjiDialog ->
//設定佈局
layoutId = R.layout.slide_view_bottom
//isLazy = true
//設定橫縱向佔滿
isFullHorizontal = true
isFullVerticalOverStatusBar = true
//陰影透明度
dimAmount = 0f
//處理事件/資料繫結
convertListenerFun { holder, dialog ->
//設定點選realView以外的部分就dismiss
holder.setOnClickListener(R.id.bottomTouchView) {
if (canClick) {
dialog.dismiss()
}
}.setOnClickListener(R.id.topTouchView) {
if (canClick) {
dialog.dismiss()
}
}
}
setOnEnterAnimator { rootView ->
//在此處設定進入動畫
AnimatorSet().apply {
duration = 500L
val realView = rootView.findViewById<View>(R.id.realView)
val touchView = rootView.findViewById<View>(R.id.bottomTouchView)
val topTouchView = rootView.findViewById<View>(R.id.topTouchView)
val maskLayout = rootView.findViewById<View>(R.id.maskLayout)
//給realView的父佈局(遮罩佈局)設定距頂部margin
maskLayout?.apply {
layoutParams = (layoutParams as ConstraintLayout.LayoutParams).apply {
topMargin = (slideForBottom.y + slideForBottom.height).toInt()
}
}
play(ObjectAnimator
.ofFloat(realView, "y", -UtilsExtension.dp2px(resources, 200f).toFloat(), 0f))
.with(ObjectAnimator
.ofFloat(touchView, "alpha", 0f, 1f))
.with(ObjectAnimator
.ofFloat(topTouchView, "alpha", 0f, 1f))
}
}
setOnExitAnimator {
//退出動畫
AnimatorSet().apply {
duration = 500L
val realView = it.findViewById<View>(R.id.realView)
val touchView = it.findViewById<View>(R.id.bottomTouchView)
val topTouchView = it.findViewById<View>(R.id.topTouchView)
play(ObjectAnimator
.ofFloat(realView, "y", 0f, -UtilsExtension.dp2px(resources, 200f).toFloat()))
.with(ObjectAnimator
.ofFloat(touchView, "alpha", 1f, 0f))
.with(ObjectAnimator
.ofFloat(topTouchView, "alpha", 1f, 0f))
}
}
}.showOnWindow(supportFragmentManager)
複製程式碼
效果圖:
基本的顯示模式都已經說了,接下來就放一個整體可見的參數列格出來
GenjiDialog中
屬性名/方法名 | 介紹 |
---|---|
rootView | layoutId所對應的佈局 |
getMyActivity() | 獲取該dialog所在的activity |
setDialogOptions(...) | 設定dialogOptions |
getDialogOptions() | 獲取dialogOptions |
extendsOptions() | 當繼承GenjiDialog時需要重寫該方法,在該方法裡面設定新的dialogOptions |
showOnWindow(...) | 將dialog顯示在螢幕中,有多個過載方法,具體可見原始碼註釋 |
showOnView(...) | 將dialog依附於某個View,有多個過載方法,具體可見原始碼註釋 |
DialogOptions
屬性名/方法名 | 介紹 |
---|---|
layoutId | 佈局id,預設:R.layout.loading_layout |
dialogStyle | dialog的樣式,一般情況下不用修改,為了方便某些朋友可能有特殊需求,所以放出來可供重寫,預設:DialogFragment.STYLE_NO_TITLE |
dialogThemeFun | dialog的主題,同上,重寫方法setDialogTheme(fun) |
setStatusBarModeFun | dialog的狀態列設定,同上,重寫方法setStatusMode(fun) |
animStyle | dialog的進出動畫,用於一般情況,內建了很多日常所需動畫,可以到res/values/styles中檢視,動畫檔案在res/anim中檢視,預設根據gravity來判斷 |
setOnEnterAnimator(fun) | dialog的進入動畫,這個動畫是用於一些特殊情況,比如上面的帶遮罩的滑出動畫,預設:null |
exitAnimator(fun) | dialog的退出動畫,同上 (這兩個動畫的示例請看上面帶遮罩滑出動畫的程式碼,也可以去原始碼檢視) |
canClick | 否可以觸發取消,預設:true,比如在動畫開始時將此屬性設定false,防止在動畫進行時,被再次觸發動畫,當使用上面兩種自定義特殊動畫時,我已經預設新增了改變這個狀態值的監聽 |
isLazy | 是否懶載入,預設:false,是否在動畫完成時才執行convertListener |
duration | 懶載入的延時,預設:0L,配合isLazy使用,這個值一般設定為動畫的時長,為了保證動畫流暢 |
dialogStatusBarColor | dialog的statusBar顏色,預設:透明,一般來說無需改變 |
width | dialog寬度,預設:0px |
height | dialog高度,預設:0px |
isFullHorizontal | dialog是否橫向佔滿,預設:false |
isFullVertical | dialog是否縱向佔滿,預設:false,該縱向佔滿並非全屏,縱向佔滿會自動扣掉狀態列的高度 |
isFullVerticalOverStatusBar | dialog是否縱向佔滿,預設:false,該縱向佔滿全屏不會扣掉狀態列高度,是真正的全屏 |
verticalMargin | dialog上下邊距,預設:0,詳細註釋請在原始碼中檢視 |
horizontalMargin | dialog左右邊距,預設:0,詳細註釋請在原始碼中檢視 |
fullVerticalMargin | dialog在上下佔滿時的邊距,預設:0px |
fullHorizontalMargin | dialog在左右佔滿時的邊距,預設:0px |
dimAmount | dialog背景的陰影的透明度:預設:0.3f |
gravity | dialog顯示為showOnWindow()時的位置:預設:DialogGravity.CENTER_CENTER |
gravityAsView | dialog顯示為showOnView()時的位置:預設:DialogGravity.CENTER_BOTTOM |
dialogViewX | x軸座標值,用於特殊動畫時定位dialog,預設:0px |
dialogViewY | y軸座標值,用於特殊動畫時定位dialog,預設:0px |
offsetX | 當dialog依附在view上時x軸的偏移量,預設:0px |
offsetX | 當dialog依附在view上時x軸的偏移量,預設:0px |
touchCancel | 是否點選螢幕區域取消(不包含返回按鈕),預設:false |
outCancel | 是否點選外部取消,預設:false,當 touchCancel == true時此屬性無效,必須是 touchCancel和該屬性均為false時,那麼點選螢幕區域和返回按鈕都不能關閉dialog |
showDismissMap | 顯示與消失的監聽map |
onKeyListener | 按鈕監聽 |
convertListener | view初始化 |
這裡我給出的屬性/方法,註釋不詳細可以到DialogOptions原始碼裡面檢視,那裡面註釋很詳細