web-dev-qa-db-de.com

Schaltfläche "Zurück" erkennen, Dialogfenster jedoch nicht schließen

Ich habe ein Dialogfenster für ein schwebendes Dialogfeld, das eine spezielle Tastatur enthält, die eingeblendet wird, wenn ein Benutzer in ein EditText-Feld drückt (der normale IME wird angehalten).

Ich möchte, dass die Tastatur verworfen wird (Sichtbarkeit = GONE), wenn der Benutzer die Zurück-Taste drückt (genau wie bei einem normalen IME-Dienst), aber der Dialog sichtbar bleibt. Es scheint jedoch keine Möglichkeit zu geben, dies zu tun, soweit ich aus meiner ziemlich ausführlichen Lektüre auf SO und anderswo sehen kann.

Wenn ich das Dialogfeld als nicht stornierbar einsetze, werde ich nicht durch onCancel () oder onDismiss () benachrichtigt, da das Dialogfeld nicht stornierbar ist.

Wenn ich den Dialog auf "Abbrechen" eingestellt habe, werde ich benachrichtigt, der Dialog wird jedoch abgebrochen.

Ich kann einen onKeyListener nicht an das Dialogfeld im Fragment anhängen, da es vom System ersetzt wird, damit das Fragment den Lebenszyklus des Dialogfelds verarbeiten kann.

Gibt es eine Möglichkeit, dies zu tun? Oder wurde der Zugriff auf die Erkennung von Schlüsselereignissen für das Fragment-System vollständig gesperrt?

54
user3227652

Der beste und sauberste Weg ist, onBackPressed () in dem von onCreateDialog () erstellten Dialog zu überschreiben.

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

Ich hatte das gleiche Problem wie Sie und es wurde behoben, dass der onKeyListener an das Dialogfenster angehängt wurde.

In die Methode onResume() der Klasse, die von DialogFragment erweitert wird, fügen Sie diesen Code ein:

    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
        }
    });

Hier ist eines der Probleme, das Sie finden können, dass dieser Code zweimal ausgeführt wird: eines, wenn der Benutzer die Zurück-Taste drückt, und ein anderes, wenn er es verlässt, um es zu drücken. In diesem Fall müssen Sie nach Ereignis filtern:

@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
        }
    });
}
56

Als Nachtrag zu Juan Pedro Martinezs Antwort dachte ich, es wäre hilfreich, wenn ich eine bestimmte Frage kläre (eine, die ich hatte), wenn ich diesen Thread anschaue.

Wenn Sie ein neues DialogFragment erstellen möchten und es so eingerichtet ist, dass der Benutzer es nur mit der Zurück-Schaltfläche abbrechen kann, wodurch verhindert wird, dass zufällige Bildschirmberührungen das Fragment vorzeitig abbrechen, ist dies der Code, den Sie verwenden würden.

In dem Code, den Sie als DialogFragment aufrufen, müssen Sie die Einstellung "cancelable" auf "false" setzen, damit NOTHING das Fragment verwirft, keine streunenden Bildschirme berühren usw.

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

Dann fügen Sie in Ihrem DialogFragment, in diesem Fall MyDaialogFragment.Java, den onResume-Überschreibungscode hinzu, damit das Dialogfeld auf die Zurück-Schaltfläche wartet. Wenn es gedrückt wird, führt es das dismiss () aus, um das Fragment zu schließen.

@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;
         }
   });

Jetzt wird Ihr Dialog mit "setCancelable" auf "false" gesetzt, was bedeutet, dass nichts (keine Klicks von außen) es abbrechen und herunterfahren kann und (innerhalb des Dialogs) nur die Zurück-Schaltfläche zulässt, um es zu schließen.

Ganbatte!

17
Brandon

Wie hat niemand das vorgeschlagen?

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;
}
6
user6367733

Verwenden Sie die Fragment onCancel-Überschreibungsmethode. Es wird aufgerufen, wenn Sie zurück drücken. Hier ist ein Beispiel: 

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

    // Add you codition
}
2
Manimaran A

Überschreiben Sie beim Erstellen des Dialogs sowohl onBackPressed als auch 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
                    ...
            }
        };
0
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    Dialog dialog = new Dialog(getActivity(), getTheme()) {
        @Override
        public void onBackPressed() {
            //your code
        }
    };

    return dialog;
}
0

Verwenden Sie onDismiss () - Callback von DialogFragment mit dem Flag closeActivity

private var closeActivity: Boolean = true    

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

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