Building a Custom Dialog with LayoutInflater in Android
A custom dialog gives an Android app more control than a standard alert box. You can place text fields, icons, buttons, checkboxes, or other views inside a reusable XML layout, then display that layout in a Dialog window. This approach keeps the interface consistent and separates visual design from Kotlin logic.
The technique is useful for login prompts, confirmation forms, filters, quick settings, and small data-entry tasks. For example, an app used by customers in Sydney or Melbourne might show a compact delivery-note form without opening a full screen. Using LayoutInflater makes that form easy to create from an XML resource and adapt for different screen sizes.
Why use a custom dialog
A standard AlertDialog works well for short messages and simple choices. A custom layout is more suitable when the user needs to enter information or interact with several controls. The XML file can contain a TextView, EditText, Spinner, ImageView, and action buttons arranged with a LinearLayout or ConstraintLayout.
The dialog should perform one focused task. A form that asks for a suburb, delivery instruction, and phone number may be appropriate, while a long registration process belongs on a dedicated screen. Keeping the interaction brief helps users complete tasks quickly, especially on smaller devices or while using an app during a commute in Brisbane or Perth.
A custom dialog also supports consistent branding. Colours, corner radius, spacing, and typography can match the rest of the application, while Android theme resources can provide light and dark mode values.
Create the dialog layout
Create a file named dialog_note.xml inside app/src/main/res/layout. The root view below uses padding and a vertical structure that can be reused for a short note form.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp">
<TextView
android:id="@+id/dialogTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Add a note"
android:textAppearance="?attr/textAppearanceHeadlineSmall" />
<EditText
android:id="@+id/noteInput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:hint="Enter a note"
android:inputType="textCapSentences|textMultiLine"
android:minLines="3" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:gravity="end"
android:orientation="horizontal">
<Button
android:id="@+id/cancelButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Cancel" />
<Button
android:id="@+id/saveButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:text="Save" />
</LinearLayout>
</LinearLayout>
Use string resources instead of hard-coded text in a production application. This supports translation and makes wording easier to update. It is also useful if the app may serve users across Australia, where clear language and localised content can matter for public-facing services.
Inflate and display the custom view
In an activity or fragment, obtain a LayoutInflater and convert the XML resource into a view object. The inflated view becomes the content of an AlertDialog.
private fun showNoteDialog() {
val inflater = LayoutInflater.from(this)
val dialogView = inflater.inflate(R.layout.dialog_note, null)
val noteInput = dialogView.findViewById<EditText>(R.id.noteInput)
val dialog = AlertDialog.Builder(this)
.setView(dialogView)
.create()
dialogView.findViewById<Button>(R.id.cancelButton).setOnClickListener {
dialog.dismiss()
}
dialogView.findViewById<Button>(R.id.saveButton).setOnClickListener {
val note = noteInput.text.toString().trim()
if (note.isEmpty()) {
noteInput.error = "Enter a note"
return@setOnClickListener
}
saveNote(note)
dialog.dismiss()
}
dialog.show()
}
The null passed as the parent is intentional when the view is later attached as the dialog’s content. If you inflate a layout for a normal screen, pass its parent and use attachToRoot = false where appropriate. The correct parent helps Android resolve layout parameters, while the dialog builder controls the final attachment.
Call the method from a button click, menu item, or another user action. The dialog is created only when needed, so the activity does not carry an unnecessary view hierarchy while it is idle.
Adjust size, style, and behaviour
By default, an alert dialog chooses a width based on the current theme and device. For a custom design, adjust the window after calling show():
dialog.show()
dialog.window?.setLayout(
(resources.displayMetrics.widthPixels * 0.90).toInt(),
WindowManager.LayoutParams.WRAP_CONTENT
)
A width of about 90 percent leaves room around the window on many phones, including devices with narrow screens. Avoid fixed pixel dimensions because Android phones and tablets have different densities. Use dp values in XML and let the content wrap naturally.
You can apply a rounded background drawable, a transparent window background, or a Material theme style when the project uses Material Components. Test the result with large font settings and both portrait and landscape orientation. A dialog that looks correct on a Pixel device in Adelaide may clip text on a smaller handset.
For longer forms, consider a ScrollView around the content. The keyboard can reduce available height, so the layout should remain usable when an EditText receives focus. Setting an appropriate windowSoftInputMode and checking keyboard behaviour on current Android versions prevents buttons from becoming hidden.
Validate input and protect user data
Validation belongs close to the action that submits the form. Check blank values, maximum lengths, and expected formats before saving. If the dialog collects a phone number or address, store only what the feature requires and explain why the data is being requested.
Australian developers should consider the Privacy Act 1988 and the Australian Privacy Principles when an app collects personal information. A local marketplace app may handle names, delivery addresses, or contact details, so dialog design should avoid exposing sensitive values unnecessarily. Do not log private input while debugging or display it in a confirmation message where another person could see the screen.
Useful interaction checks
- Give the primary action a clear, specific label.
- Keep the cancel action available and easy to reach.
- Show validation errors beside the relevant field.
- Dismiss the dialog after a successful save.
Accessibility checks
- Provide meaningful labels and hints for input controls.
- Maintain readable contrast in light and dark themes.
- Ensure buttons can be reached with keyboard or switch navigation.
- Test with TalkBack and enlarged system text.
Dialogs should also handle dismissal consistently. A user may tap outside the window or press the back button, so do not treat every dismissal as a completed action. Save only after the positive button has passed validation.
Choose the right implementation
A DialogFragment is often a stronger option when the dialog must survive configuration changes. A direct AlertDialog is simpler for a short interaction inside an activity, while a custom view is useful when the same form appears in several places.
The following comparison helps select an approach for a new Android feature:
| Approach | Best use | Strength | Limitation |
|---|---|---|---|
Standard AlertDialog |
Short message or simple choice | Fast to implement | Limited visual structure |
AlertDialog with inflated XML |
Compact form or branded prompt | Flexible layout and familiar API | Requires lifecycle care |
DialogFragment |
Reusable or rotation-sensitive dialog | Better lifecycle integration | More setup and state handling |
| Full-screen activity or fragment | Multi-step or lengthy input | Plenty of space and navigation | Heavier interaction |
For a small note editor, inflating dialog_note.xml into an AlertDialog is usually sufficient. For an app used across Australian cities, tested on different network conditions and a broad device range, the same design should be checked with offline data, slow loading, and restored state after rotation. This keeps the custom window focused, readable, and dependable wherever the user opens it.