webentwicklung-frage-antwort-db.com.de

Wie kann ich den Dialog mit einem Klick außerhalb des Dialogs beenden?

Ich habe einen benutzerdefinierten Dialog für meine Anwendung implementiert. Ich möchte das implementieren, wenn der Benutzer außerhalb des Dialogs klickt, wird der Dialog verworfen. Was muss ich dafür tun?

137
iDroid Explorer

Sie können dialog.setCanceledOnTouchOutside(true); verwenden, um den Dialog zu schließen, wenn Sie außerhalb des Dialogs berühren.

So etwas wie,

  Dialog dialog = new Dialog(context)
  dialog.setCanceledOnTouchOutside(true);

Oder wenn Ihr Dialog dann nicht im Modell ist,

1 - Setzen Sie das Flag -FLAG_NOT_TOUCH_MODAL für das Fensterattribut Ihres Dialogs

Window window = this.getWindow();
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);

2 - Fügen Sie den Fenstereigenschaften ein weiteres Flag hinzu, FLAG_WATCH_OUTSIDE_TOUCH - Dieses Dialogfeld dient dazu, ein Berührungsereignis außerhalb des sichtbaren Bereichs zu empfangen.

3 - Überschreiben Sie onTouchEvent() des Dialogs und überprüfen Sie den Aktionstyp. Wenn der Aktionstyp 'MotionEvent.ACTION_OUTSIDE 'bedeutet, interagiert der Benutzer außerhalb des Dialogbereichs. In diesem Fall können Sie also Ihren Dialog verkleinern oder entscheiden, was Sie ausführen möchten.

public boolean onTouchEvent(MotionEvent event)  
{  

       if(event.getAction() == MotionEvent.ACTION_OUTSIDE){  
        System.out.println("TOuch outside the dialog ******************** ");  
               this.dismiss();  
       }  
       return false;  
}  

Weitere Informationen finden Sie unter Wie kann ich ein benutzerdefiniertes Dialogfeld basierend auf Berührungspunkten abweisen? und So schließen Sie Ihren nichtmodalen Dialog, wenn Sie außerhalb des Dialogbereichs berühren

327
user370305

Sie können diese Implementierung von onTouchEvent verwenden. Es verhindert, dass auf das Berührungsereignis (wie howettl) unter Aktivität reagiert wird.

@Override
public boolean onTouchEvent ( MotionEvent event ) {
  // I only care if the event is an UP action
  if ( event.getAction () == MotionEvent.ACTION_UP ) {
    // create a rect for storing the window rect
    Rect r = new Rect ( 0, 0, 0, 0 );
    // retrieve the windows rect
    this.getWindow ().getDecorView ().getHitRect ( r );
    // check if the event position is inside the window rect
    boolean intersects = r.contains ( (int) event.getX (), (int) event.getY () );
    // if the event is not inside then we can close the activity
    if ( !intersects ) {
      // close the activity
      this.finish ();
      // notify that we consumed this event
      return true;
    }
  }
  // let the system handle the event
  return super.onTouchEvent ( event );
}

Quelle: http://blog.twimager.com/2010/08/closing-activity-by-touching-outside.html

16
Lukas Novak

Einfach verwenden 

dialog.setCanceledOnTouchOutside(true);
14
Ebin Sebastian

Wenn Sie das Dialogfeld mit einem in Ihrer XML-Formatvorlage definierten Design anpassen, fügen Sie diese Zeile in Ihr Design ein:

<item name="Android:windowCloseOnTouchOutside">true</item>
9
Chris.Zou
dialog.setCanceledOnTouchOutside(true); 

um den Dialog bei Berührung außerhalb zu schließen.

Und wenn Sie die Berührung von außen nicht schließen möchten, verwenden Sie den folgenden Code:

dialog.setCanceledOnTouchOutside(false);
6
Naveen

Bei dieser Methode sollten Aktivitäten unterhalb des grauen Bereichs vollständig vermieden werden, indem Klickereignisse abgerufen werden.

Entfernen Sie diese Zeile, wenn Sie es haben:

window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);

Setzen Sie dies auf Ihre erstellte Aktivität

getWindow().setFlags(LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);

dann überschreiben Sie das Berührungsereignis mit diesem

@Override
public boolean onTouchEvent(MotionEvent ev)
{
    if(MotionEvent.ACTION_DOWN == ev.getAction())
    {
        Rect dialogBounds = new Rect();
        getWindow().getDecorView().getHitRect(dialogBounds);
        if (!dialogBounds.contains((int) ev.getX(), (int) ev.getY())) {
            // You have clicked the grey area
            displayYourDialog();
            return false; // stop activity closing
        }
    }

    // Touch events inside are fine.
    return super.onTouchEvent(ev);
}
5
Unknownweirdo

Sie können dies versuchen: -

AlterDialog alterdialog;
alertDialog.setCanceledOnTouchOutside(true);

oder

alertDialog.setCancelable(true);

Und wenn Sie einen AlterDialog.Builder haben, können Sie folgendes versuchen: -

alertDialogBuilder.setCancelable(true);
4

Dieser Code wird verwendet, wenn beim Klicken auf das Dialogfeld die Zeit eingeblendet wird und wenn der Benutzer auf die äußere Seite des Dialogfelds klickt, wenn sowohl der Soft-Input als auch das Dialogfeld geschlossen sind.

dialog = new Dialog(act) {
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // Tap anywhere to close dialog.
        Rect dialogBounds = new Rect();
        getWindow().getDecorView().getHitRect(dialogBounds);
        if (!dialogBounds.contains((int) event.getX(),
                (int) event.getY())) {
            // You have clicked the grey area
            InputMethodManager inputMethodManager = (InputMethodManager) act
                    .getSystemService(act.INPUT_METHOD_SERVICE);
            inputMethodManager.hideSoftInputFromWindow(dialog
                    .getCurrentFocus().getWindowToken(), 0);
            dialog.dismiss();
            // stop activity closing
        } else {
            InputMethodManager inputMethodManager = (InputMethodManager) act
                    .getSystemService(act.INPUT_METHOD_SERVICE);
            inputMethodManager.hideSoftInputFromWindow(dialog
                    .getCurrentFocus().getWindowToken(), 0);
        }

        return true;
    }
};
2
Maulik Santoki

Bei einer anderen Lösung wurde dieser Code aus dem Android-Quellcode von Window .__ abgeschnitten. Sie sollten diese beiden Methoden einfach zum Dialog-Quellcode hinzufügen. 

@Override
public boolean onTouchEvent(MotionEvent event) {        
    if (isShowing() && (event.getAction() == MotionEvent.ACTION_DOWN
            && isOutOfBounds(getContext(), event) && getWindow().peekDecorView() != null)) {
        hide();
    }
    return false;
}

private boolean isOutOfBounds(Context context, MotionEvent event) {
    final int x = (int) event.getX();
    final int y = (int) event.getY();
    final int slop = ViewConfiguration.get(context).getScaledWindowTouchSlop();
    final View decorView = getWindow().getDecorView();
    return (x < -slop) || (y < -slop)
            || (x > (decorView.getWidth()+slop))
            || (y > (decorView.getHeight()+slop));
}

Diese Lösung hat dieses Problem nicht: 

Dies funktioniert hervorragend, mit der Ausnahme, dass die Aktivität darunter auch auf das Berührungsereignis reagiert. Gibt es eine Möglichkeit, dies zu verhindern? - Howettl

2
Lemberg

Rufen Sie dialog.setCancelable(false); aus Ihrer Aktivität/Ihrem Fragment auf.

0
EKN

Sie können eine background machen, die die gesamte Bildschirmgröße transparent einnimmt, und das onClick-Ereignis auf dismiss hören.

0
oriolpons