Обнаружить кнопку "Назад", но не отклонять диалоговое окно
У меня есть диалоговоефрагмент для плавающего диалога, который включает специальную клавиатуру, которая появляется, когда пользователь нажимает внутри поля EditText (нормальный IME остановлен от отображения).
Я хотел бы, чтобы клавиатура была отклонена (visibility = GONE), когда пользователь нажимает кнопку "Назад" (как и на обычную службу IME), но диалог остается видимым. Тем не менее, похоже, не существует способа сделать это, насколько я могу видеть из моего довольно обширного чтения о SO и в других местах.
Если я установил, что диалог не отменяется, я не получаю уведомления от onCancel() или onDismiss(), потому что диалог не отменяется.
Если я установил диалог для отмены, я получаю уведомление, но диалог отклоняется.
Я не могу прикрепить onKeyListener к диалогу в фрагменте, потому что он заменяется системой, так что фрагмент может обрабатывать жизненный цикл диалога.
Есть ли способ сделать это? Или есть доступ к обнаружению ключевых событий, которые были полностью отгорожены для целей системы Фрагмента?
Ответы
Ответ 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
}
}
});