Dialog fragment and custom positioning
Alert dialog
Use it when you just want to show a title
, up to three buttons
, a list of selectable items
, or a custom layout
.
Also DatePickerDialog
and TimePickerDialog
are available with a pre-defined android style widgets, that allows the user to select a date or time.
DialogFragment
Use a DialogFragment as a container for your dialog, when you need
- to ensures that it correctly handles lifecycle events such as when the user presses the back button or rotates the screen.
- to allow reuse the dialog’s UI just like in a traditional Fragment (such as when you want the dialog UI to appear differently on large and small screens).
class FireMissilesDialogFragment : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle): Dialog {
return requireActivity()?.let {
// Use the Builder class for convenient dialog construction
val builder = AlertDialog.Builder(it)
builder.setMessage(R.string.dialog_fire_missiles)
.setPositiveButton(R.string.fire,
DialogInterface.OnClickListener { dialog, id ->
})
.setNegativeButton(R.string.cancel,
DialogInterface.OnClickListener { dialog, id ->
// User cancelled the dialog
})
// Create the AlertDialog object and return it
builder.create()
} ?: throw IllegalStateException("Activity cannot be null")
}
}
// Showing a Dialog
fun confirmFireMissiles() {
val newFragment = FireMissilesDialogFragment()
newFragment.show(supportFragmentManager, "missiles")
}
The show method add the fragment in transaction and commits, however you can not pop back this fragment from stack.
class CustomDialogFragment : DialogFragment() {
/** The system calls this to get the DialogFragment's layout, regardless
of whether it's being displayed as a dialog or an embedded fragment. */
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
// Inflate the layout to use as dialog or embedded fragment
return inflater.inflate(R.layout.purchase_items, container, false)
}
/** The system calls this only when creating the layout in a dialog. */
override fun onCreateDialog(savedInstanceState: Bundle): Dialog {
// The only reason you might override this method when using onCreateView() is
// to modify any dialog characteristics. For example, the dialog includes a
// title by default, but your custom layout might not need it. So here you can
// remove the dialog title, but you must call the superclass to get the Dialog.
val dialog = super.onCreateDialog(savedInstanceState)
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
return dialog
}
}
fun showDialog() {
val fragmentManager = supportFragmentManager
val newFragment = CustomDialogFragment()
if (isLargeLayout) {
// The device is using a large layout, so show the fragment as a dialog
newFragment.show(fragmentManager, "dialog")
} else {
// The device is smaller, so show the fragment fullscreen
val transaction = fragmentManager.beginTransaction()
// For a little polish, specify a transition animation
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
// To make it fullscreen, use the 'content' root view as the container
// for the fragment, which is always the root view for the activity
transaction
.add(android.R.id.content, newFragment)
.addToBackStack(null)
.commit()
}
}
Changing the position of the dialog.
private fun setupDialogProperties(alertDialog: AlertDialog) {
val OFFSET_IN_PX = 140
alertDialog.apply {
window?.let { window ->
window.setBackgroundDrawableResource(R.drawable.bg_drawable)
window.setDimAmount(0.1f) // from 0 for no dim to 1 for full dim.
window.attributes?.let { params ->
params.width = WindowManager.LayoutParams.MATCH_PARENT
params.height = WindowManager.LayoutParams.WRAP_CONTENT
params.gravity = Gravity.TOP or Gravity.CENTER
params.y = (OFFSET_IN_PX).toFloat())
params.x = 0
}
}
setCanceledOnTouchOutside(true)
setCancelable(true)
requestWindowFeature(Window.FEATURE_NO_TITLE)
}
}