Create AlertDialog with complex custom layout programmatically

Create AlertDialog with Custom Layout using XML Layout

Sometimes we may have to create the AlertDialog with custom layout. But the custom layout needs to be created programatically. This tutorial is about creating an AlertDialog similar to the login screen. But, the views are added programmatically, instead of creating and inflating an XML layout inside it. If you want to inflate the layout using XML, then please follow this tutorial.

This post is the fifth in series of tutorials for creating and displaying AlertDialog.

Series Index of AlertDialog

  1. Create AlertDialog and Basic Usage
  2. Provide Selection from a list of options
  3. Create AlertDialog with Custom Layout using XML Layout
  4. Create AlertDialog with custom layout programmatically
  5. Create AlertDialog with complex custom layout programmatically
  6. Override Button of AlertDialog

Prepare layout (main_activity.xml)

This layout will display a button which will open the AlertDialog.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/btn_show_dialog"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/show_dialog"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Custom EditText to set default LayoutParams

Let’s create a custom EditText to set default LayoutParams, so that we don’t have to set it again and again on all EditText we use.

package com.pcsalt.example.customalertdialogdemo2

import android.content.Context
import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
import android.widget.LinearLayout
import androidx.appcompat.widget.AppCompatEditText

class MyEditText(context: Context?) : AppCompatEditText(context!!) {
    init {
        this.setSingleLine()
        this.imeOptions = EditorInfo.IME_ACTION_DONE
        setImeActionLabel("Done", EditorInfo.IME_ACTION_DONE)
        this.layoutParams = LinearLayout.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.WRAP_CONTENT
        )
    }
}

Update MainActivity.kt to display the custom AlertDialog layout

In showCustomDialog() method we are going to create different elements EditText, TextView and LinearLayouts to create one custom view.

package com.pcsalt.example.customalertdialogdemo2

import android.os.Bundle
import android.text.method.PasswordTransformationMethod
import android.view.View
import android.widget.EditText
import android.widget.LinearLayout
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        findViewById<View>(R.id.btn_show_dialog).setOnClickListener { showCustomDialog() }
    }

    private fun showCustomDialog() {
        val llMainLayout = LinearLayout(this)
        llMainLayout.orientation = LinearLayout.VERTICAL
        llMainLayout.setPadding(60, 10, 40, 10)

        val llUserLayout = LinearLayout(this)
        llUserLayout.orientation = LinearLayout.HORIZONTAL
        llUserLayout.setPadding(10, 10, 10, 10)

        val llPasswordLayout = LinearLayout(this)
        llPasswordLayout.orientation = LinearLayout.HORIZONTAL
        llPasswordLayout.setPadding(10, 10, 10, 10)

        val etUsername: EditText = MyEditText(this)
        val tvUsername = TextView(this)
        tvUsername.text = getString(R.string.username)

        val etPassword: EditText = MyEditText(this)
        etPassword.transformationMethod = PasswordTransformationMethod.getInstance()
        val tvPassword = TextView(this)
        tvPassword.text = getString(R.string.password)

        llUserLayout.addView(tvUsername)
        llUserLayout.addView(etUsername)

        llPasswordLayout.addView(tvPassword)
        llPasswordLayout.addView(etPassword)

        llMainLayout.addView(llUserLayout)
        llMainLayout.addView(llPasswordLayout)

        val alert = AlertDialog.Builder(this)
        alert.setTitle("Custom Login")
        alert.setView(llMainLayout)
        alert.setCancelable(false)
        alert.setPositiveButton("Login") { _, _ ->
            val user = etUsername.text.toString()
            val pass = etPassword.text.toString()
            Toast.makeText(this@MainActivity, "User: $user Password: $pass", Toast.LENGTH_SHORT).show()
        }
        alert.setNegativeButton("Cancel") { dialog, _ -> dialog.dismiss() }
        val dialog = alert.create()
        dialog.show()
    }
}

Screenshots

Download Source Code

The complete source code is pushed to GitHub repo. Browse it by clicking on the octocat icon.

Browse source code on GitHub