Is there any way to use Kotlin Anko Alertdialog with handling screen rotation changes?

415 views Asked by At

Using Anko library is pretty easy, but when i rotate screen, my dialog dismisses. The only way how to avoid this is to use child of DialogFragment() with method show(fm, TAG).

So we need to override method onCreateDialog(savedInstanceState: Bundle?): Dialog which returns Dialog instance. But Anko's alert{ }.build() returns DialogInterface instance

So, is there any way to use anko in this situation?

alert {
        message = "Message"                   
        positiveButton("OK") {
            //stuff
        }
        negativeButton("NOT OK") {
            //stuff
        }
}.show()

EDIT

So, that what I did. I've created abstract BaseDialogFragment:

abstract class BaseDialogFragment : DialogFragment() {

    abstract val ankoAlert: AlertBuilder<DialogInterface>

    protected var dialogListener: DialogListener? = null

    protected val vm by lazy {
        act.getViewModel(DialogViewModel::class)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        dialogListener = parentFragment as? DialogListener
    }

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog =
            (ankoAlert.build() as? Dialog)
                    ?: error("Anko DialogInterface is no longer backed by Android Dialog")
}

Then I've created some dialogs, like that:

class MyDialogFragment : BaseDialogFragment() {

    companion object {
        fun create() = MyDialogFragment ()
    }

    override val ankoAlert: AlertBuilder<DialogInterface>
        get() = alert {
            negativeButton(R.string.app_canceled) {
                dialogListener?.onDismiss?.invoke()
            }
            customView = createCustomView(vm.data)
        }

    fun createCustomView(data: Data): View {
        //returning view
    }
}

Also my DialogListener is sort of that:

interface DialogListener {

    var onDismiss: () -> Unit

    val onClick: (Data) -> Unit

    var onPostClick: (Data) -> Unit

}

And finally, in parent fragment we can use:

MyDialogFragment.create().show(childFragmentManager, MyDialogFragment::class.java.simpleName)

Hope it will help somebody.

2

There are 2 answers

0
Ge3ng On BEST ANSWER

From the Android Documentation, Dialog implements DialogInterface. So all known subclasses of Dialog including AlertDialog implement that interface.

You can cast and return the result from the build as follows:

return alert {
    message = "Message"                   
    positiveButton("OK") {
        //stuff
    }
    negativeButton("NOT OK") {
        //stuff
    }
}.build() as Dialog

This will work but if Anko ever changes its implementation you will get a ClassCastException. To get a cleaner error you can use the following.

val dialogInterface = alert {
    message = "Message"                   
    positiveButton("OK") {
        //stuff
    }
    negativeButton("NOT OK") {
        //stuff
    }
}.build()
return (dialogInterface as? Dialog) ?: error("Anko DialogInterface is no longer backed by Android Dialog")

This gives you a more explicit error, but most likely won't be needed.

0
Abu Noman On

If you don't have dynamic UI then you can use android:configChanges="orientation" in your activity in manifest, look likes:

<activity android:name=".MainActivity"
   android:configChanges="orientation">
...
</activity>