Como lidar com o botão Voltar na caixa de diálogo?

95

Estou desenvolvendo um aplicativo que, quando o botão é pressionado, abre uma caixa de diálogo com os botões OK e Cancelar.

Funciona bem.

Quando o usuário pressiona o botão Voltar, estou lidando com isso da seguinte maneira

public boolean onKeyDown(int keyCode, KeyEvent event) 
{
    if ((keyCode == KeyEvent.KEYCODE_BACK)) 
    {

    }
 return super.onKeyDown(keyCode, event);
}

Mas o método acima não é chamado. Como posso lidar com isso?

Kiran
fonte
1
Você deseja que o usuário possa cancelar a caixa de diálogo? Ou o que sua parte onKeyDown faz?
Krueger
@kiran :: pode ser um pouco mais claro ??
KMI

Respostas:

238
dialog.setOnKeyListener(new Dialog.OnKeyListener() {

            @Override
            public boolean onKey(DialogInterface arg0, int keyCode,
                    KeyEvent event) {
                // TODO Auto-generated method stub
                if (keyCode == KeyEvent.KEYCODE_BACK) {
                    finish();
                    dialog.dismiss();
                }
                return true;
            }
        });
Yasin Hassanien
fonte
8
não há necessidade de descartar o Dialog; finish()cuida disso já. Além disso, este método provavelmente deve retornar falsepara ser capaz de capturar eventos importantes em outro lugar
slinden77
6
Acho que a resposta do alexc abaixo é uma alternativa melhor.
Simon Forsberg
23
Eu adicionei o && event.getAction() == KeyEvent.ACTION_UPà resposta. Sem ele, o bloco de código será executado duas vezes. (Tecle ABAIXO e tecle ACIMA). Neste exemplo, não é tão importante, mas para outras ações além de terminar (), pode ser muito importante.
Udo Klimaschewski
1
@dmmh se você não ligar, dialog.dismiss()ocorrerá um vazamento de memória.
CONvid19,
2
Tenho certeza que você está certo, mas nesse caso finish()e dialog.dismiss()deve ser alternado no código acima.
slinden77
115

Parece que você deseja definir o OnCancelListener ao criar a caixa de diálogo. Se parece com isso:

dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {         
    @Override
    public void onCancel(DialogInterface dialog) {
        //do whatever you want the back key to do
    }
});
alexc
fonte
7
Esta é definitivamente a melhor resposta. Bom e simples. Não há necessidade de detectar o KeyEvent. Perfeito.
LargeGlasses
2
Eu sei que estou muito atrasado, mas pensei em apontar algo. Além disso, isso também será acionado quando o usuário clicar em algum lugar fora da caixa de diálogo. Portanto, se você precisa apenas substituir a opção de pressionar de volta, não é isso que você está procurando.
user2520215
5
@ user2520215 se você não quiser que seja disparado quando o usuário clicar fora da caixa de diálogo, você deve definir dialog.setCanceledOnTouchOutside (false). Esta é definitivamente a melhor resposta.
Alhassan Abdulkadir
Obrigado por apontar. Esta é certamente uma abordagem melhor.
user2520215
3
Isso não parece funcionar se uma visão personalizada for usada (ou seja, não criando a caixa de diálogo, mas apenas herdando de DialogFragment) enquanto o ouvinte de chave funciona nesse caso.
Julian Honma
19

Você precisa substituir o OnCancelmétodo. Este método chama a tecla Voltar. Aqui está o código que funciona perfeitamente para mim.

 AlertDialog alertDialog;

    alertDialog.setOnCancelListener(new OnCancelListener() 
    {                   
           @Override
            public void onCancel(DialogInterface dialog) 
             {
               // TODO Auto-generated method stub

                    dialog.dismiss();                           

            }
}); 

Espero que isso ajude você e aceite-o se for útil para você.

Obrigado..

Nunca desistir
fonte
7

Tente isto

 new AlertDialog.Builder(this).setOnKeyListener(new DialogInterface.OnKeyListener() {

                        @Override
                        public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {

                            if(keyCode == KeyEvent.KEYCODE_BACK){
                                Logger.d(TAG, "--------- Do Something -----------");
                                return true;
                            }
                            return false;


                        }
                    })
NitZRobotKoder
fonte
1
Por que não posso usar setOnCancelListener no Builder?
ffleandro
2

Se você estiver usando um DialogFragment, pelo que posso dizer que a maneira certa de fazer isso é sobrescrever onCancel ()

Percebi setOnCancelListenerque não funciona e setOnKeyListenerfunciona, mas para mim tem o efeito colateral divertido de engolir todas as teclas se sua caixa de diálogo tiver um texto de edição.

Daniel Wilson
fonte
1

é porque quando sua caixa de diálogo é aberta, sua janela é direcionada para a caixa de diálogo. Então agora você tem que lidar keycom o seu Diálogo.

Mohammed Azharuddin Shaikh
fonte
Embora correta, esta resposta não é muito informativa sobre como lidar keycom o Diálogo.
Simon Forsberg
1

Substitua o método onBackPressed()em sua própria caixa de diálogo e use-o em seu código:

public class MyDialog extends Dialog {

    public MyDialog(@NonNull Context context) {
        super(context);
    }

    @Override
    public void onBackPressed() {
        // Do what you want
    }
}

Usar:

MyDialog dlg = new MyDialog(context);
dlg.show();
Santamoniya
fonte
0

Este código funciona:

    Dialog dlg = new Dialog(thisAct, R.style.DialogTheme);
    dlg.setContentView(view);
    dlg.setCancelable(false);
    dlg.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
    dlg.setOnKeyListener((arg0, keyCode, event) -> {
        Timber.d("onKey(%d)", keyCode);
        //{home intercepting
        if ((keyCode == KeyEvent.KEYCODE_HOME)) {
            Timber.i("HOME pressed");
            return true;
        }

        return true;
    });
    dlg.show();
Andrew Glukhoff
fonte