Android DialogFragment快速使用方法

第二篇 解決DialogFragment狀態(tài)欄亮色問(wèn)題 - 簡(jiǎn)書 (jianshu.com)

前言

很多人抱怨原生的Dialog不好用,自定義方式比較復(fù)雜,這里介紹一下如何使用官方推薦的DialogFragment

使用方法

首先要意識(shí)到DialogFragment的本質(zhì)就是一個(gè)Fragment,實(shí)現(xiàn)DialogInterface,能夠?yàn)殚_發(fā)者提供更多便捷的操作。

  • 初始化
    Fragment相同,重寫onCreateView加載布局
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    return inflater.inflate(R.layout.custom_layout, container, false)
}

其中,R.layou.custom_layout是自己定義的布局文件

  • 顯示與隱藏
    Dialog一樣,使用show()方法顯示,但是在DialogFragment中,show()方法需要傳入一個(gè)FragmentManager保證DialogFragment能夠被正確的添加到Activity中。在使用show()方法時(shí),建議重寫該方法并判斷isAdded
dialogFragment.show(supportFragmentManager) // In Activity
dialogFragment.show(parentFragmentManager) // In Fragment

隱藏DialogFragment,如果使用dismiss()方法會(huì)導(dǎo)致某些不可預(yù)期的錯(cuò)誤,很多網(wǎng)友也分析過(guò),建議使用dismissAllowingStateLoss()替代

默認(rèn)背景

系統(tǒng)自帶的Dialog是有背景的,通常自定義的時(shí)候會(huì)嚴(yán)重影響美觀,需要加上這兩句話用來(lái)去掉默認(rèn)的背景:

 override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    dialog?.requestWindowFeature(Window.FEATURE_NO_TITLE)
    dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
}

如果想調(diào)整背景陰影的透明度,使用dimAmount,數(shù)值從0.0 ~ 1.0,數(shù)字越小越透明,默認(rèn)值為0.6

override fun onResume() {
    dialog?.window?.attributes?.dimAmount = 0.6f
}

全屏顯示

網(wǎng)上查閱了很多資料,大部分都說(shuō)要使用style的方式,效果很不錯(cuò),但是我測(cè)試的時(shí)候,dimAmount和動(dòng)畫無(wú)法使用了,我目前使用以下方法解決全屏的問(wèn)題,雖然不夠完美,但目前來(lái)看是最優(yōu)的方式:

override fun onResume() {
    super.onResume()
    dialog?.window?.setLayout(
        ViewGroup.LayoutParams.MATCH_PARENT,
        ViewGroup.LayoutParams.MATCH_PARENT
    )
}

UI刷新

這是一個(gè)令人頭疼的問(wèn)題,Fragment創(chuàng)建的時(shí)候我們并不知道UI什么時(shí)候能繪制完成,如果在創(chuàng)建DialogFragment實(shí)例就傳參刷新UI,大概率會(huì)導(dǎo)致崩潰,既然本質(zhì)是Fragment,就可以按照對(duì)付Fragment的思路去對(duì)付DialogFragment

  • 創(chuàng)建一個(gè)抽象類,繼承DialogFragment
abstract class BaseDialog : DialogFragment{ }
  • 使用LiveData,綁定生命周期
val dialogData = MutableLiveData<Any?>()
  • 創(chuàng)建一個(gè)供外部調(diào)用的方法,傳入我們需要的數(shù)據(jù)
fun updateData(data: Any?) {
    dialogData.postValue(data)
}
  • 創(chuàng)建數(shù)據(jù)回調(diào)(Listener方式)
private var dataListener: ((Any?) -> Unit)? = null

override fun onViewCreated(view: View, savedInstanceState: Bundle?){
    super.onViewCreated(view, savedInstanceState)
    dialogData.observe(viewLifecycleOwner) { dataListener?.invoke(it) }
}

fun setOnDataListener(listener: (Any?) -> Unit) {
    this.dataListener = listener
}

//子類中調(diào)用監(jiān)聽
setOnDataListener { data ->  // TODO  根據(jù)data的數(shù)據(jù)類型執(zhí)行不同的UI邏輯 }
  • 創(chuàng)建數(shù)據(jù)回調(diào)(Abstract方式)
abstract fun onUpdate(data: Any?)

override fun onViewCreated(view: View, savedInstanceState: Bundle?){
    super.onViewCreated(view, savedInstanceState)
    dialogData.observe(viewLifecycleOwner) { onUpdate?.invoke(it) }
}

//在子類中重寫onUpdate方法
override fun onUpdate(data:Any?){
    //TODO 根據(jù)data的數(shù)據(jù)類型執(zhí)行不同的UI邏輯
}

小結(jié)

DialogFragment乍一看使用起來(lái)挺麻煩,但其本質(zhì)就是一個(gè)Fragment,我們基本可以使用對(duì)待Fragment的思路去處理問(wèn)題。
本人能力有限,學(xué)識(shí)淺薄,只能描述自己遇到的一些問(wèn)題,如果有寫的不好的地方歡迎批評(píng)。

補(bǔ)充

注意一點(diǎn):如果要在DialogFragment中嵌套一個(gè)Fragment,需要使用childFragmentManager來(lái)添加新的Fragment

工作中要涉及到萬(wàn)惡的舊版本(Api <= 22),設(shè)置全屏?xí)@示狀態(tài)欄,需要修改View的屬性:

 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
     val window = dialog?.window
     if (window != null) {
     val uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
              View.SYSTEM_UI_FLAG_FULLSCREEN or
              View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
     dialog?.window?.decorView?.systemUiVisibility = uiOptions
     }
}

如果是使用 Api30及其以上,這里會(huì)出現(xiàn)很多@Deprecated刪除線,不要緊張,新的Api只能在新版中使用,這里可能Studio沒有處理。用以上方式可以消除狀態(tài)欄,但是,彈出dialog的時(shí)候,狀態(tài)欄會(huì)閃一下馬上消失,暫時(shí)沒有更完美的解決方法,如果有請(qǐng)留言,感激不盡。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容