Android 默认对话框是不带优先级的,并且可以同时弹出多个,最后弹出的在最上面。往往我们更习惯一次只显示一个对话框,然后前一个关闭后一个才弹出。于是有了PriorityDialog
PriorityDialog基于DialogFragment实现,以最小的倾入性实现优先级对话框。
dependencies {
implementation 'com.github.qq549631030:priority-dialog:x.x.x'
}
在Application的onCreate方法调用PriorityDialogManager.init(this)初始化
class BaseApplication : Application() {
override fun onCreate() {
super.onCreate()
PriorityDialogManager.init(this)
}
}
通过代理方式:
PriorityDialog by PriorityDialogImpl()可实现将任意一个DialogFragment转变成优先级对话框
open class BaseDialog : DialogFragment(), PriorityDialog by PriorityDialogImpl() {
}
通过代理方式:
DialogManager by DialogManagerImpl() 可实现将任意一个FragmentActivity转变成对话框管理类
DialogHost by DialogHostImpl() 可实现将任意一个FragmentActivity、Fragment转变成对话框宿主
open class BaseActivity : AppCompatActivity(), DialogManager by DialogManagerImpl(),
DialogHost by DialogHostImpl() {
}
open class BaseFragment : Fragment(), DialogHost by DialogHostImpl() {
}
在DialogHost(宿主)中调用showPriorityDialog(priorityDialog)即可
val dialog = BaseDialog()
dialog.priorityConfig.priority = 1
showPriorityDialog(dialog)
当同一宿主页面同时有多个对话框弹出时,优先级最高的先显示,等高优先级的关闭后,次优先级的再弹出。
分三种情况:
1、先低后高,高取代低显示,高关闭后低再显示
val dialog1 = BaseDialog()
dialog1.priorityConfig.priority = 1
showPriorityDialog(dialog1)
//当前显示dialog1
val dialog2 = BaseDialog()
dialog2.priorityConfig.priority = 2
showPriorityDialog(dialog2)
//当前显示dialog2
dialog2.dismiss()
//当前显示dialog1
dialog1.dismiss()
//当前无dialog
2、先高后低,低不显示,高关闭后低再显示
val dialog1 = BaseDialog()
dialog1.priorityConfig.priority = 2
showPriorityDialog(dialog1)
//当前显示dialog1
val dialog2 = BaseDialog()
dialog2.priorityConfig.priority = 1
showPriorityDialog(dialog2)
//当前仍然显示dialog1
dialog1.dismiss()
//当前显示dialog2
dialog2.dismiss()
//当前无dialog
3、同优先级,后弹出的优先级高
val dialog1 = BaseDialog()
dialog1.priorityConfig.priority = 1
showPriorityDialog(dialog1)
//当前显示dialog1
val dialog2 = BaseDialog()
dialog2.priorityConfig.priority = 1
showPriorityDialog(dialog2)
//当前显示dialog2
dialog2.dismiss()
//当前显示dialog1
dialog1.dismiss()
//当前无dialog
以上是默认的优先级处理方式,也可以通过配置PriorityStrategy来自定义规则
通过PriorityDialogManager.init(this,priorityStrategy)初始化全局策略
或通过PriorityDialogManager.updatePriorityStrategy(priorityStrategy)修改全局策略
也可以通过DialogManager.setCurrentPriorityStrategy(priorityStrategy)来设置单个Activity的策略
具体实现方式可参数DefaultPriorityStrategy
public interface PriorityStrategy {
//新对话框是否能取代现有对话框而显示
boolean canNewShow(@NonNull PriorityDialog preDialog, @NonNull PriorityDialog newDialog);
//新对话框和等待队列里的比是否能显示,默认true
boolean canNewShowCasePending(@NonNull List<PendingDialogState> pendingList, @NonNull PriorityDialog newDialog);
//等待队列中相同优先级的对话框弹出顺序是不是先进先出,默认false
boolean firstInFirstOutWhenSamePriority();
}
如前面情况1,低被高取代,当高关闭后低会再次显示,如果想低不再显示,可以设置低 isAddToPendingWhenReplaceByOther=false
val dialog1 = BaseDialog()
dialog1.priorityConfig.priority = 1
dialog1.priorityConfig.isAddToPendingWhenReplaceByOther = false
showPriorityDialog(dialog1)
//当前显示dialog1
val dialog2 = BaseDialog()
dialog2.priorityConfig.priority = 2
showPriorityDialog(dialog2)
//当前显示dialog2
dialog2.dismiss()
//当前无dialog
若为true则对话框显示时只能停留在当前页面,无法关闭无法跳走,会把这些操作缓存起来,当对话框关闭时会自动执行之前未执行的操作。
Activity的 startActivity()、startActivityForResult()、finish()
Fragment的 startActivity()、startActivityForResult()
要使这个属性生效,前面的BaseActivity配置要做如下调整:
open class BaseActivity : AppCompatActivity(), DialogManager by DialogManagerImpl(),
DialogHost by DialogHostImpl() {
override fun startActivityForResult(intent: Intent, requestCode: Int, options: Bundle?) {
if (warpStartActivityForResult(intent, requestCode, options)) {
return
}
super.startActivityForResult(intent, requestCode, options)
}
override fun finish() {
if (warpFinish()) {
return
}
super.finish()
}
}
val dialog = BaseDialog()
dialog.priorityConfig.isLockWindow = true
showPriorityDialog(dialog)
//当前显示dialog
startActivity(Intent(this, SecondActivity::class.java))
finish()
//SecondActivity不会启动,当前页面不会关闭
dialog.dismiss()
//SecondActivity启动,当前页面关闭
FragmentManager的各种Transaction以及popBackStack
要使这个属性生效,执行Transaction以及popBackStack操作时要使用warpParentFragmentManager或者warpChildFragmentManager
val dialog = BaseDialog()
dialog.priorityConfig.isLockWindow = true
showPriorityDialog(dialog)
//当前显示dialog
warpParentFragmentManager.beginTransaction().replace(R.id.container, SecondFragment()).commit()
//当前显示的Fragment不变
dialog.dismiss()
//当前显示的Fragment变成了SecondFragment
val dialog = BaseDialog()
dialog.priorityConfig.isSupportRecreate = true
showPriorityDialog(dialog)
//当前显示dialog
//Activity recreate
//当前显示dialog
val dialog = BaseDialog()
dialog.priorityConfig.isSupportRecreate = false
showPriorityDialog(dialog)
//当前显示dialog
//Activity recreate
//当前无dialog
默认在stop状态下弹对话框会被丢弃,可以通过设置isAllowStateLoss来改变这一行为
val dialog = BaseDialog()
//activity.onStop()
showPriorityDialog(dialog)
//当前无dialog
//activity.onResume()
//当前无dialog
dialog.priorityConfig.isAllowStateLoss = true
//activity.onStop()
showPriorityDialog(dialog)
//当前无dialog
//activity.onResume()
//当前有dialog
默认想弹的对话框比现在显示中或者比等待队列中最高优先级对话框(isCasePending=true时)的优先级低会加入等待队列, 可以通过设置isAddToPendingWhenCanNotShow来改变这一行为
val dialog1 = BaseDialog()
dialog1.priorityConfig.priority = 2
showPriorityDialog(dialog1)
//当前显示dialog1
val dialog2 = BaseDialog()
dialog2.priorityConfig.priority = 1
dialog2.priorityConfig.isAddToPendingWhenCanNotShow = false
showPriorityDialog(dialog2)
//当前仍然显示dialog1(dialog2被丢弃)
dialog1.dismiss()
//当前无dialog
默认被其它高优先级对话框顶下去的时候要加入等待队列,可以通过设置isAddToPendingWhenReplaceByOther = false来改变这一行为
val dialog1 = BaseDialog()
dialog1.priorityConfig.priority = 1
dialog1.priorityConfig.isAddToPendingWhenReplaceByOther = false
showPriorityDialog(dialog1)
//当前显示dialog1
val dialog2 = BaseDialog()
dialog2.priorityConfig.priority = 2
showPriorityDialog(dialog2)
//当前显示dialog2(dialog1被丢弃)
dialog2.dismiss()
//当前无dialog
默认正在显示的对话框关闭后,等待队列里最高优先级的一个会立即弹出,可以通过设置isShowImmediateAfterPreDismiss = false来改变这一行为
之后可通过DialogManager.tryShowNextPendingDialog()或者DialogManager.tryShowPendingDialog(dialogInfo)
来手动显示等待队列中的对话框
val dialog1 = BaseDialog()
dialog1.priorityConfig.priority = 1
dialog21.priorityConfig.isShowImmediateAfterPreDismiss = false
showPriorityDialog(dialog1)
//当前显示dialog1
val dialog2 = BaseDialog()
dialog2.priorityConfig.priority = 2
showPriorityDialog(dialog2)
//当前显示dialog2
dialog2.dismiss()
//当前无dialog (dialog1还在笔队列中)
tryShowNextPendingDialog()
//当前显示dialog1
默认要弹对话框的时候只和现在正在显示的对话框比较优先级,不考虑等待队列中的,可以通过设置isCasePending = true来改变这一行为
val dialog1 = BaseDialog()
dialog1.priorityConfig.priority = 2
dialog1.priorityConfig.isShowImmediateAfterPreDismiss = false
showPriorityDialog(dialog1)
//当前显示dialog1
val dialog2 = BaseDialog()
dialog2.priorityConfig.priority = 3
showPriorityDialog(dialog2)
//当前显示dialog2
dialog2.dismiss()
//当前无dialog (dialog1还在笔队列中)
val dialog3 = BaseDialog()
dialog3.priorityConfig.priority = 1
dialog3.priorityConfig.isCasePending = true
showPriorityDialog(dialog3)
//当前显示dialog1(dialog3进入等待队列)
dialog1.dismiss()
//当前显示dialog3
默认情况下,当想要弹的对话框比等待队列里最高优先级的对话框优先级低时,等待队列中最高优先级的对话框会自动弹出,可以通过设置isShowImmediateAfterPreCanNotShowCasePending = false来改变这一行为
val dialog1 = BaseDialog()
dialog1.priorityConfig.priority = 2
dialog1.priorityConfig.isShowImmediateAfterPreDismiss = false
dialog1.priorityConfig.isShowImmediateAfterPreCanNotShowCasePending = false
showPriorityDialog(dialog1)
//当前显示dialog1
val dialog2 = BaseDialog()
dialog2.priorityConfig.priority = 3
showPriorityDialog(dialog2)
//当前显示dialog2
dialog2.dismiss()
//当前无dialog (dialog1还在笔队列中)
val dialog3 = BaseDialog()
dialog3.priorityConfig.priority = 1
dialog3.priorityConfig.isCasePending = true
showPriorityDialog(dialog3)
//当前无dialog(dialog1,dialog3都在等待孤队列)
tryShowNextPendingDialog()
//当前显示dialog1
dialog1.dismiss()
//当前显示dialog3
有时候你的对话框行为和框架默认的不一样,但不想每次弹框都重复性的设置这些属性,可以能过这个方法统一设置
open class BaseDialog : DialogFragment(), PriorityDialog by PriorityDialogImpl() {
override fun defaultPriorityConfig(config: PriorityDialogConfig) {
//低优先级的直接丢弃,不加入等待队列
config.isAddToPendingWhenCanNotShow = false
config.isAddToPendingWhenReplaceByOther = false
}
}
可重写DialogHost的onCancel方法(推荐)
override fun onCancel(priorityDialog: PriorityDialog) {
if (priorityDialog.uuid == "custom_uuid") {
//next
}
}
也可用setOnCancelListener
dialog.setOnCancelListener(object : OnCancelListener {
override fun onCancel(dialog: PriorityDialog) {
//这里只能通过dialog.dialogHost访问外部类的方法、属性
//不可直接访问外部类方法、属性,因为Activity recreate后的情况下原dialogHost已经不存在了
(dialog.dialogHost as? YourHostActivity)?.publicMethod()
//(dialog.dialogHost as? YourHostFragment)?.publicMethod()
}
})
可重写DialogHost的onDismiss方法(推荐)
override fun onDismiss(priorityDialog: PriorityDialog) {
if (priorityDialog.uuid == "custom_uuid") {
//next
}
}
也可用setOnDismissListener
dialog.setOnDismissListener(object : OnDismissListener {
override fun onDismiss(dialog: PriorityDialog) {
//这里只能通过dialog.dialogHost访问外部类的方法、属性
//不可直接访问外部类方法、属性,因为Activity recreate后的情况下原dialogHost已经不存在了
(dialog.dialogHost as? YourHostActivity)?.publicMethod()
//(dialog.dialogHost as? YourHostFragment)?.publicMethod()
}
})
可重写DialogHost的onDialogEvent方法(推荐)
event可以是任意的自定义事件,比如按钮点击,文字输入等等。
override fun onDialogEvent(priorityDialog: PriorityDialog, event: Any) {
if (priorityDialog.uuid == "custom_uuid") {
when (event) {
is BaseAlertDialog.AlertDialogClickEvent -> {
if (event.which == DialogInterface.BUTTON_POSITIVE) {
//next
}
}
else -> {}
}
}
}
也可用setOnDialogEventListener
dialog.setOnDialogEventListener(object : OnDialogEventListener {
override fun onDialogEvent(dialog: PriorityDialog, event: Any) {
//这里只能通过dialog.dialogHost访问外部类的方法、属性
//不可直接访问外部类方法、属性,因为Activity recreate后的情况下原dialogHost已经不存在了
(dialog.dialogHost as? YourHostActivity)?.publicMethod()
//(dialog.dialogHost as? YourHostFragment)?.publicMethod()
}
})
registerPriorityDialogListener() unregisterPriorityDialogListener()
open class BaseActivity : AppCompatActivity(), DialogManager by DialogManagerImpl(),
DialogHost by DialogHostImpl() {
private val priorityDialogListener = object : PriorityDialogListener {
override fun onDialogShow(dialog: PriorityDialog) {
//对话框显示
}
override fun onDialogDismiss(dialog: PriorityDialog) {
//对话框关闭
}
override fun onDialogAddToPending(dialog: PriorityDialog) {
//对话框加入等待队列
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
registerPriorityDialogListener(priorityDialogListener)
}
override fun onDestroy() {
unregisterPriorityDialogListener(priorityDialogListener)
super.onDestroy()
}
}
//获取所有等待队列对话框
getAllPendingDialog()
//手动弹出等待队列中最高优先级对话框
tryShowNextPendingDialog()
//手动弹出等待队列中指定对话框(这个方法可以先显示低优先级的)
tryShowPendingDialog(dialogInfo)