Подтвердить что ты не робот

Обнаружить кнопку "Назад", но не отклонять диалоговое окно

У меня есть диалоговоефрагмент для плавающего диалога, который включает специальную клавиатуру, которая появляется, когда пользователь нажимает внутри поля EditText (нормальный IME остановлен от отображения).

Я хотел бы, чтобы клавиатура была отклонена (visibility = GONE), когда пользователь нажимает кнопку "Назад" (как и на обычную службу IME), но диалог остается видимым. Тем не менее, похоже, не существует способа сделать это, насколько я могу видеть из моего довольно обширного чтения о SO и в других местах.

Если я установил, что диалог не отменяется, я не получаю уведомления от onCancel() или onDismiss(), потому что диалог не отменяется.

Если я установил диалог для отмены, я получаю уведомление, но диалог отклоняется.

Я не могу прикрепить onKeyListener к диалогу в фрагменте, потому что он заменяется системой, так что фрагмент может обрабатывать жизненный цикл диалога.

Есть ли способ сделать это? Или есть доступ к обнаружению ключевых событий, которые были полностью отгорожены для целей системы Фрагмента?

4b9b3361

Ответ 1

Лучший способ и самый чистый способ - переопределить onBackPressed() в диалоговом окне, созданном в onCreateDialog().

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    return new Dialog(getActivity(), getTheme()){
        @Override
        public void onBackPressed() {
            //do your stuff
        }
    };
}

Ответ 2

У меня была такая же проблема, как у вас, и я исправил ее, добавив onKeyListener в диалоговом фрагменте.

В методе onResume() класса, который распространяется на DialogFragment, поместите эти фрагменты кода:

    getDialog().setOnKeyListener(new OnKeyListener()
    {
        @Override
        public boolean onKey(android.content.DialogInterface dialog, int keyCode,android.view.KeyEvent event) {

            if ((keyCode ==  android.view.KeyEvent.KEYCODE_BACK))
                {
                     //Hide your keyboard here!!!
                     return true; // pretend we've processed it
                }
            else 
                return false; // pass on to be processed as normal
        }
    });

Здесь одна из проблем, которые вы можете найти, - это код, который будет выполняться дважды: один, когда пользователь нажимает кнопку "назад", а другой - на него. В этом случае вы должны фильтровать по событию:

@Override
public void onResume() {
    super.onResume();

    getDialog().setOnKeyListener(new OnKeyListener()
    {
        @Override
        public boolean onKey(android.content.DialogInterface dialog, int keyCode,
                android.view.KeyEvent event) {

            if ((keyCode ==  android.view.KeyEvent.KEYCODE_BACK))
            {
                //This is the filter
                if (event.getAction()!=KeyEvent.ACTION_DOWN)
                        return true;
                else
                {
                    //Hide your keyboard here!!!!!!
                    return true; // pretend we've processed it
                }
            } 
            else 
                return false; // pass on to be processed as normal
        }
    });
}

Ответ 3

В качестве добавления к Juan Pedro Martinez ответ я подумал, что было бы полезно прояснить конкретный вопрос (тот, который у меня был) при просмотре этой темы.

Если вы хотите создать новый DialogFragment и иметь его, чтобы пользователь мог только отменить его с помощью кнопки "Назад" , что устраняет случайные экраны при отмене фрагмента преждевременно, тогда это код, который вы будете использовать.

В коде, который вы вызываете DialogFragment, вам нужно установить для параметра cancelable значение false, чтобы НИЧЕГО не отклоняло фрагмент, ни один экран не касался экрана и т.д.

DialogFragment mDialog= new MyDialogFragment();
mDialog.setCancelable(false);
mDialog.show(getFragmentManager(), "dialog");

Затем, в вашем диалоговом окне "Диалог", в этом случае MyDaialogFragment.java, вы добавляете код переопределения onResume, чтобы диалоговое окно прослушивало кнопку "Назад" . Когда он будет нажат, он выполнит функцию увольнения(), чтобы закрыть фрагмент.

@Override
 public void onResume() 
 {
     super.onResume();

     getDialog().setOnKeyListener(new OnKeyListener()
     {
         @Override
         public boolean onKey(android.content.DialogInterface dialog, 
                              int keyCode,android.view.KeyEvent event) 
         {
              if ((keyCode ==  android.view.KeyEvent.KEYCODE_BACK))
              {
                   // To dismiss the fragment when the back-button is pressed.
                   dismiss();
                   return true;
              }
              // Otherwise, do nothing else
              else return false;
         }
   });

Теперь ваш диалог будет вызван с "setCancelable" на false, что означает, что ничего (без внешних кликов) может отменить его и закрыть его, а также разрешить (из самого диалогового окна) только кнопку "Назад" , чтобы закрыть его.

Ganbatte!

Ответ 4

Как никто не предложил это?

public Dialog onCreateDialog(Bundle savedInstanceState) {
  Dialog dialog = super.onCreateDialog(savedInstanceState);

  // Add back button listener
  dialog.setOnKeyListener(new Dialog.OnKeyListener() {
    @Override
    public boolean onKey(DialogInterface dialogInterface, int keyCode, KeyEvent keyEvent) {
      // getAction to make sure this doesn't double fire
      if (keyCode == KeyEvent.KEYCODE_BACK && keyEvent.getAction() == KeyEvent.ACTION_UP) {
        // Your code here
        return true; // Capture onKey
      }
      return false; // Don't capture
    }
  });

  return dialog;
}

Ответ 5

Используйте метод переопределения Fragment onCancel. Он вызывается, когда вы нажимаете назад. вот образец:

@Override
public void onCancel(DialogInterface dialog) {
    super.onCancel(dialog);

    // Add you codition
}

Ответ 6

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    Dialog dialog = new Dialog(getActivity(), getTheme()) {
        @Override
        public void onBackPressed() {
            //your code
        }
    };

    return dialog;
}

Ответ 7

При создании диалога переопределите как onBackPressed, так и onTouchEvent:

        final Dialog dialog = new Dialog(activity) {
            @Override
            public boolean onTouchEvent(final MotionEvent event) {
                //note: all touch events that occur here are outside the dialog, yet their type is just touching-down
                boolean shouldAvoidDismissing = ... ;
                if (shouldAvoidDismissing) 
                    return true;
                return super.onTouchEvent(event);
            }

            @Override
            public void onBackPressed() {
                boolean shouldAvoidDismissing = ... ;
                if (!shouldSwitchToInviteMode)
                    dismiss();
                else
                    ...
            }
        };

Ответ 8

Используйте onDismiss() обратный вызов DialogFragment с флагом closeActivity

private var closeActivity: Boolean = true    

override fun onDismiss(dialog: DialogInterface?) {
        super.onDismiss(dialog)

        if (closeActivity) {
            activity!!.finish()
        }
    }

Ответ 9

Используйте этот фрагмент, чтобы обнаружить onBackClick поверх фрагмента диалога.

AlertDialog alertDialog = dialog.create();
alertDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
     @Override
     public void onCancel(DialogInterface dialog) {
         Log.i(TAG, "onCancel: dialog");
         if(listener != null) {
             // calback listener
         }
     }
 });