'MaterialAlertDialogBuilder for DialogPreferences in PreferenceFragments
In preference screens, I'd like to use MaterialComponent's dialogs (using MaterialAlertDialogBuilder
) instead of AlertDialog
from AppCompat. However, AppCompat's preference framework hardcodes using the AlertDialog.Builder
.
From what I can see, the only way to override this is to override: PreferenceFragmentCompat.onDisplayPreferenceDialog()
and copy a bunch of the logic from that superclass (in terms of showing the dialog fragment etc).
Is this the correct approach or is there a better way?
Solution 1:[1]
Here is my solution for ListPreference
:
class MaterialListPreferenceDialogFragment : ListPreferenceDialogFragmentCompat() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val context: Context? = activity
mWhichButtonClicked = DialogInterface.BUTTON_NEGATIVE
val builder = MaterialAlertDialogBuilder(requireActivity())
.setTitle(preference.dialogTitle)
.setIcon(preference.dialogIcon)
.setPositiveButton(preference.positiveButtonText, this)
.setNegativeButton(preference.negativeButtonText, this)
val contentView = onCreateDialogView(context)
if (contentView != null) {
onBindDialogView(contentView)
builder.setView(contentView)
} else {
builder.setMessage(preference.dialogMessage)
}
onPrepareDialogBuilder(builder)
val dialog = builder.create()
//if (needInputMethod()) {
// requestInputMethod(dialog)
//}
return dialog
}
/* Override the methods that access mWhichButtonClicked (because we cannot set it properly here) */
/** Which button was clicked. */
private var mWhichButtonClicked = 0
override fun onClick(dialog: DialogInterface?, which: Int) {
mWhichButtonClicked = which
}
override fun onDismiss(dialog: DialogInterface) {
onDialogClosedWasCalledFromOnDismiss = true
super.onDismiss(dialog)
}
private var onDialogClosedWasCalledFromOnDismiss = false
override fun onDialogClosed(positiveResult: Boolean) {
if (onDialogClosedWasCalledFromOnDismiss) {
onDialogClosedWasCalledFromOnDismiss = false
// this means the positiveResult needs to be calculated from our mWhichButtonClicked
super.onDialogClosed(mWhichButtonClicked == DialogInterface.BUTTON_POSITIVE)
} else {
super.onDialogClosed(positiveResult)
}
}
}
fun PreferenceFragmentCompat.showListPreferenceDialog(preference: ListPreference) {
val dialogFragment = MaterialListPreferenceDialogFragment().apply {
arguments = Bundle(1).apply {
putString("key", preference.key)
}
}
dialogFragment.setTargetFragment(this, 0)
dialogFragment.show(parentFragmentManager, "androidx.preference.PreferenceFragment.DIALOG")
}
and then in the PreferenceFragmentCompat
subclass:
override fun onDisplayPreferenceDialog(preference: Preference) {
if (preference is ListPreference) {
showListPreferenceDialog(preference)
} else {
super.onDisplayPreferenceDialog(preference)
}
}
Feedback welcome!
Solution 2:[2]
For me it looks like adding this to my theme makes the preference dialog appear in material design:
<item name="alertDialogTheme">@style/ThemeOverlay.MaterialComponents.MaterialAlertDialog</item>
At least the font & color are being adapted, the dialog corners however are still not as rounded as the on coming from MaterialAlertDialogBuilder
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Edric |
Solution 2 | Edric |