8

I have an AlertDialog and its setCancelable() is false. In Onbackpressed function I want the AlertDialog to be closed. But when setCancelable() is false, the back key doesn't work at all. What should I do to get rid of this problem? I don't want to change setCancelable() to true because I will have another problem.

import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {
    lateinit var dialogBuilder: AlertDialog.Builder
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        dialogBuilder = AlertDialog.Builder(this)
        dialogBuilder.setMessage("Check your internet connection")
            .setPositiveButton("OK") { _, _ ->
                Toast.makeText(this, "OK", Toast.LENGTH_LONG).show()
            }.setCancelable(false)
            .create().show()
    }
}
MMG
  • 3,226
  • 5
  • 16
  • 43

5 Answers5

7

just add a onKeyListener and cancel dialog on back key event.

    lateinit var dialog: AlertDialog

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        dialog = AlertDialog.Builder(this).setMessage("Check your internet connection")
                .setPositiveButton("OK") { _, _ ->
                    Toast.makeText(this, "OK", Toast.LENGTH_LONG).show()
                }.setCancelable(false)
                .create()
        dialog.show()

        dialog.setOnKeyListener { _, keyCode, _ ->
            if(keyCode == KeyEvent.KEYCODE_BACK) {
                if(dialog.isShowing) {
                    dialog.dismiss()
                }
            }
            true
        }
    }
Alif Hasnain
  • 1,176
  • 1
  • 11
  • 24
5

The easiest work-around for this problem is to set an OnKeyListener and automatically detect when the user hits the back button.

Java:

public Dialog onCreateDialog(Bundle savedInstanceState) {

  Dialog dialog = super.onCreateDialog(savedInstanceState);

  dialog.setOnKeyListener(new Dialog.OnKeyListener() {
    @Override
    public boolean onKey(DialogInterface dialogInterface, int keyCode, KeyEvent keyEvent) {
        if (keyCode == KeyEvent.KEYCODE_BACK && keyEvent.getAction() == KeyEvent.ACTION_UP) {
          dialog.cancel;
          return true;
        }
        return false;
    }
  });

  return dialog;
}

Kotlin:

    dialog = AlertDialog.Builder(this)
            .setCancelable(false)
            .create()
    dialog.show()

    dialog.setOnKeyListener (object : Dialog.OnKeyListener { 
      override fun onKey(dialogInterface: DialogInterface, keyCode: Int, keyEvent: KeyEvent) {
        if(keyCode == KeyEvent.KEYCODE_BACK and keyEvent.action == KeyEvent.ACTION_UP) {
            dialog.dismiss()
            true
        }
        false
      }})

Note that I added an extra condition in the if-statement, all this does is to make sure this does not fire twice.

I hope this helps you.

Taslim Oseni
  • 6,086
  • 10
  • 44
  • 69
5

As i see you create dialogBuilder is public why not you call this in a public alertDialog and than show it using alertDilog.show() and close on back pressClick in activity and dismiss the dialog alertDilog.dismiss() override the onBackPress and dismiss it here

val alertDialog:AlertDialog?=null


         alertDialog = new AlertDialog.Builder(this)
        //set icon 
        .setIcon(android.R.drawable.ic_dialog_alert)
        //set title
        .setTitle("Are you sure to Exit")
        //set message
        .setMessage("Exiting will call finish() method")
        //set positive button
        .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialogInterface, int i) {
        //set what would happen when positive button is clicked    
            finish();
        }
        })
        //set negative button
        .setNegativeButton("No", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialogInterface, int i) {
        //set what should happen when negative button is clicked
            Toast.makeText(getApplicationContext(),"Nothing 
          Happened",Toast.LENGTH_LONG).show();
         }
        })
        .show();

       onBackPress(){alertDialog.dismiss()}
MMG
  • 3,226
  • 5
  • 16
  • 43
Amit pandey
  • 1,149
  • 1
  • 4
  • 15
3
dialogBuilder.setOnKeyListener(object : OnKeyListener() {
            fun onKey(dialog: DialogInterface, keyCode: Int, event: KeyEvent?): Boolean {
                if (keyCode == KeyEvent.KEYCODE_BACK) {
//if you want to cancel the dialog only
                    dialog.cancel()
                    //if you want to finish then 
                   // finish()
                }
                return true
            }
        })
Wahdat Jan
  • 3,988
  • 3
  • 21
  • 46
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/209657/discussion-on-answer-by-wahdat-kashmiri-not-working-onbackpressed-when-setcancel). – Samuel Liew Mar 15 '20 at 11:02
3

if you don't want to close the dialog when touched outside area of the dialog, you can set the property

    permissionDialog.setCanceledOnTouchOutside(false)

and if you want to dismiss the dialog on backpress you need to call the method on keyListener

 permissionDialog?.setOnKeyListener { dialog, keyCode, _ ->
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            dialog?.dismiss()
            true
        }
        false
    }
Raza
  • 791
  • 7
  • 22