androidkotlinandroid-alertdialog

Android Kotlin findViewById must not be null


We have created a custom alert dialog that was used in a Java project by converting it to Kotlin The error posted below java.lang.IllegalStateException: findViewById(R.id.btnYES) must not be null

The error source is eluding us ! We have looked at a number of posts and tried a few with no results. The Activity structure is as follows PageTwoActivity has its own XML file with two buttons attached. The custom dialog has its own xml file Here is the PageTwoActivity code. Without the two buttons for PageTwoActivity NO name conflicts

import android.app.Dialog
import android.content.Intent
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.EditText
import android.widget.Toast

class PageTwoActivity : AppCompatActivity() {
internal lateinit var btnBACK: Button
internal lateinit var btnDIALOG: Button

internal lateinit var btnYES: Button
internal lateinit var btnNO: Button
internal lateinit var etStudentName:EditText
var EnteredText: String = ""

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_page_two)

    btnBACK = findViewById(R.id.btnBACK)
    btnDIALOG = findViewById(R.id.btnDIALOG)

    btnYES = findViewById(R.id.btnYES)
    btnNO = findViewById(R.id.btnNO)
    etStudentName = findViewById(R.id.etStudentName)
    addListenerOnButtonBACK()
    addListenerOnButtonDIALOG()

    Toast.makeText(this@PageTwoActivity, "You are on Page Two", 
    Toast.LENGTH_LONG).show()

}// END onCreate

Here is the code for the Custom Dialog

    private fun doCustom() {

    val openDialog = Dialog(this)
    openDialog.setContentView(R.layout.custom_dialog)
    //val btnYES = view!!.findViewById<Button>(R.id.btnYES)
    //val btnNO = openDialog.findViewById(R.id.btnNO)
    //val etStudentName = openDialog.findViewById(R.id.etStudentName)
    openDialog.setCancelable(false)


    btnYES.setOnClickListener(View.OnClickListener {
        EnteredText = etStudentName.getText().toString().trim({ it <= ' ' })
        if (EnteredText.isEmpty()) {
            Toast.makeText(applicationContext, "Enter Your Name\n\n OR Click 
     DECLINE", Toast.LENGTH_LONG).show()
            return@OnClickListener
        }
        Toast.makeText(applicationContext, "Registered $EnteredText", 
        Toast.LENGTH_SHORT).show()
        openDialog.dismiss()
    })

    btnNO.setOnClickListener(View.OnClickListener {
        EnteredText = ""
        val intent = Intent(this@PageTwoActivity, MainActivity::class.java)
        startActivity(intent)
        openDialog.dismiss()
    })
    openDialog.show()
}

The XML file code for the custom dialog

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="400dp"
android:layout_height="200dp"
android:background="@color/color_lightGray">

<TextView
    android:id="@+id/tvDAT"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="70dp"
    android:layout_marginTop="30dp"
    android:text="Enter First and Last Name"
    android:textColor="@color/color_Black"
    android:textSize="22sp"
    android:textStyle="bold" />

<EditText
    android:id="@+id/etStudentName"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="20dp"
    android:layout_marginTop="80dp"
    android:ems="14"
    android:gravity="center"
    android:inputType="textPersonName"
    android:text=""
    android:textColor="@color/color_Black"
    android:textSize="20sp"
    android:textStyle="bold" />

<Button
    android:id="@+id/btnYES"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="250dp"
    android:layout_marginTop="120dp"
    android:background="@color/color_Transparent"
    android:text="TAKE QUIZ"
    android:textColor="@color/color_deepBlue"
    android:textSize="22sp"
    android:textStyle="bold" />

<Button
    android:id="@+id/btnNO"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="22dp"
    android:layout_marginTop="120dp"
    android:background="@color/color_Transparent"
    android:text="DECLINE"
    android:textColor="@color/color_deepBlue"
    android:textSize="22sp"
    android:textStyle="bold" />

   </RelativeLayout>

So the question is how do we FIX the error? Should we be inflating the custom dialog xml? As you can see we tried to move the declaration to find the id into the doCustom function //val btnYES = view!!.findViewById(R.id.btnYES) this link offers advice but we have no idea where to start LINK


Solution

  • As @Declan Nnadozie already mentioned: btnYES = findViewById(R.id.btnYES) returns null because btnYES is not a view inside the contentView inflated to PageTwoActivity.
    The buttons btnYES and btnNO and the EditText etStudentName can be found in the content that is inflated in the dialog:
    Also in Kotlin you do not need findViewById to access the activity's views.
    You can delete all these:

    internal lateinit var btnBACK: Button
    internal lateinit var btnDIALOG: Button
    
    internal lateinit var btnYES: Button
    internal lateinit var btnNO: Button
    internal lateinit var etStudentName:EditText
    

    My suggestion is to use the below code:

    class PageTwoActivity : AppCompatActivity() {
    var EnteredText: String = ""
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_page_two)
    
            addListenerOnButtonBACK()
            addListenerOnButtonDIALOG()
    
            Toast.makeText(this@PageTwoActivity, "You are on Page Two",
                Toast.LENGTH_LONG).show()
        }
    
        fun doCustom(v: View) {
            val openDialog = Dialog(this)
            openDialog.setContentView(R.layout.custom_dialog)
            val btnYES = openDialog.findViewById<Button>(R.id.btnYES)
            val btnNO = openDialog.findViewById<Button>(R.id.btnNO)
            val etStudentName = openDialog.findViewById<EditText>(R.id.etStudentName)
            openDialog.setCancelable(false)
    
            btnYES.setOnClickListener(View.OnClickListener {
                EnteredText = etStudentName.getText().toString().trim({ it <= ' ' })
                if (EnteredText.isEmpty()) {
                    Toast.makeText(applicationContext, "Enter Your Name\n\n OR Click DECLINE", Toast.LENGTH_LONG).show()
                            return@OnClickListener
                }
                Toast.makeText(applicationContext, "Registered $EnteredText", Toast.LENGTH_SHORT).show()
                openDialog.dismiss()
            })
    
            btnNO.setOnClickListener(View.OnClickListener {
                EnteredText = ""
                val intent = Intent(this@PageTwoActivity, MainActivity::class.java)
                startActivity(intent)
                openDialog.dismiss()
            })
            openDialog.show()
        }