"The specified child already has a parent. You must call removeView() on the child's parent first" the second time I create an AlertDialog

Viewed 1231

When I click on the button for the first time, it runs normally. But when I click on it for the second time, the program crashes: The specified child already has a parent. You must call removeView() on the child's parent first.

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {

        binding = ActivityMainBinding.inflate(layoutInflater)
        super.onCreate(savedInstanceState)
        setContentView(binding.root)

        val view1 = layoutInflater.inflate(R.layout.main_view1, null, false)

        val btn1 = view1.findViewById<Button>(R.id.btn1)
        val btn2 = view1.findViewById<Button>(R.id.btn2)
        val btn3 = view1.findViewById<Button>(R.id.btn3)

        btn1.setOnClickListener {
            binding.textView.setTextColor(Color.RED)
        }
        btn2.setOnClickListener {
            binding.textView.setTextColor(Color.BLUE)
        }
        btn3.setOnClickListener {
            binding.textView.setTextColor(Color.GREEN)
        }

        binding.button.setOnClickListener {

            AlertDialog.Builder(this)
                .setTitle("Color")
                .setView(view1)
                .setCancelable(false)
                .setPositiveButton("ok", DialogInterface.OnClickListener { _, _ ->
                })
                .create().show()
        }

    }
}
1 Answers

The problem is that you're creating and holding a reference to view1 once:

    val view1 = layoutInflater.inflate(R.layout.main_view1, null, false)

but then trying to use that same view every time the button is clicked:

    binding.button.setOnClickListener {

        AlertDialog.Builder(this)
            .setTitle("Color")
            .setView(view1)
            .setCancelable(false)
            .setPositiveButton("ok", DialogInterface.OnClickListener { _, _ ->
            })
            .create().show()
    }

To solve it, you should move your setup code inside the button click listener, so that you get a fresh view1 for each new AlertDialog:

    binding.button.setOnClickListener {
        val view1 = layoutInflater.inflate(R.layout.main_view1, null, false)

        val btn1 = view1.findViewById<Button>(R.id.btn1)
        val btn2 = view1.findViewById<Button>(R.id.btn2)
        val btn3 = view1.findViewById<Button>(R.id.btn3)

        btn1.setOnClickListener {
            binding.textView.setTextColor(Color.RED)
        }
        btn2.setOnClickListener {
            binding.textView.setTextColor(Color.BLUE)
        }
        btn3.setOnClickListener {
            binding.textView.setTextColor(Color.GREEN)
        }

        AlertDialog.Builder(this)
            .setTitle("Color")
            .setView(view1)
            .setCancelable(false)
            .setPositiveButton("ok", DialogInterface.OnClickListener { _, _ ->
            })
            .create().show()
    }
Related