Comment fermer la boîte de dialogue en cliquant en dehors de la boîte de dialogue?


Réponses:


356

Vous pouvez utiliser dialog.setCanceledOnTouchOutside(true);ce qui fermera la boîte de dialogue si vous touchez en dehors de la boîte de dialogue.

Quelque chose comme,

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

Ou si votre boîte de dialogue n'est pas un modèle alors,

1 - Définissez le drapeau- FLAG_NOT_TOUCH_MODALpour l'attribut de fenêtre de votre boîte de dialogue

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

2 - Ajoutez un autre drapeau aux propriétés de Windows ,, FLAG_WATCH_OUTSIDE_TOUCH- celui-ci est pour que le dialogue reçoive un événement tactile en dehors de sa région visible.

3 - Remplacer la onTouchEvent()boîte de dialogue et vérifier le type d'action. si le type d'action est « MotionEvent.ACTION_OUTSIDE» signifie que l'utilisateur interagit en dehors de la zone de dialogue. Donc, dans ce cas, vous pouvez fermer votre boîte de dialogue ou décider de ce que vous souhaitez effectuer. voir le papier ordinaire?

public boolean onTouchEvent(MotionEvent event)  
{  

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

Pour plus d'informations, consultez Comment fermer une boîte de dialogue personnalisée basée sur les points de contact? et Comment fermer votre boîte de dialogue non modale, lorsqu'elle est touchée en dehors de la zone de dialogue


9
Cela fonctionne très bien, sauf que l'activité en dessous réagit également à l'événement tactile. Y a-t-il un moyen d'éviter cela?
howettl

Ouais. window.setFlags (WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL); provoque ce problème. J'ai posté une solution ci-dessous :)
Unknownweirdo

Est-il possible de propager des événements «au contact de l'extérieur» à l'activité sous-jacente en utilisant également une boîte de dialogue non personnalisée?
jc

1
@howettl J'ai résolu votre problème dans ma solution que j'ai publiée ci-dessous où je n'ai pas besoin de définir d'indicateur sur window.
Roman Nazarevych

@MuhammedRefaat - Veuillez consulter ce fil de discussion groups.google.com/forum/#!topic/android-developers/VhaiIMl6E_w . Ils l'ont bien décrit.
user370305

18

Utilisez simplement

dialog.setCanceledOnTouchOutside(true);

Je sais que cela devrait être la bonne réponse, mais cela ne fonctionne pas pour moi, et je ne sais tout simplement pas pourquoi.
IgniteCoders

16

Vous pouvez utiliser cette implémentation de onTouchEvent. Il empêche de réagir sous l'activité à l'événement tactile (comme mentionné howettl).

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

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


9

Ou, si vous personnalisez la boîte de dialogue à l'aide d'un thème défini dans votre style xml, mettez cette ligne dans votre thème:

<item name="android:windowCloseOnTouchOutside">true</item>

Cela ne fonctionne pas pour moi sur Samsung Galaxy Tab 2 WiFi. dialog.setCanceledOnTouchOutside(true);fonctionne à merveille.
doplumi

7
dialog.setCanceledOnTouchOutside(true); 

pour fermer le dialogue au toucher à l'extérieur.

Et si vous ne voulez pas fermer au toucher à l'extérieur, utilisez le code ci-dessous:

dialog.setCanceledOnTouchOutside(false);

6

Cette méthode doit complètement éviter les activités sous la zone grise de récupération des événements de clic.

Supprimez cette ligne si vous l'avez:

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

Mettez ceci sur votre activité créée

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

puis écraser l'événement tactile avec ce

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

4

Vous pouvez essayer ceci: -

AlterDialog alterdialog;
alertDialog.setCanceledOnTouchOutside(true);

ou

alertDialog.setCancelable(true);

Et si vous avez un AlterDialog.Builderalors vous pouvez essayer ceci: -

alertDialogBuilder.setCancelable(true);

4

Ce code est utilisé lors de l'utilisation, cliquez sur la boîte de dialogue pour masquer l'entrée logicielle et lorsque l'utilisateur clique sur le côté extérieur de la boîte de dialogue, lorsque l'entrée logicielle et la boîte de dialogue sont fermées.

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

Une autre solution, ce code a été tiré du code source Android de Window Vous devez simplement ajouter ces deux méthodes au code source de votre boîte de dialogue.

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

Cette solution n'a pas ce problème:

Cela fonctionne très bien, sauf que l'activité en dessous réagit également à l'événement tactile. Y a-t-il un moyen d'éviter cela? - hurlement


Ne pouvez-vous pas simplement rendre votre boîte de dialogue modale si vous ne voulez pas que d'autres fenêtres reçoivent des événements?

1

Appelez dialog.setCancelable(false);depuis votre activité / fragment.



0

Vous pouvez faire un backgroundoccupant toute la taille de l'écran transparentet écouter l' onClickévénement dismiss.


10
Très mauvaise réponse! Bien sûr, cela peut être fait, mais faites-le de la bonne façon!
jc

-1

Voici le code

    dialog.getWindow().getDecorView().setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent ev) {

            if(MotionEvent.ACTION_DOWN == ev.getAction())
            {
                Rect dialogBounds = new Rect();
                dialog. getWindow().getDecorView().getHitRect(dialogBounds);
                if (!dialogBounds.contains((int) ev.getX(), (int) ev.getY())) {
                    // You have clicked the grey area
                    UiUtils.hideKeyboard2(getActivity());
                    return false; // stop activity closing
                }
            }
            getActivity().dispatchTouchEvent(ev);
            return false;
        }
    });

Essaye celui-là . vous pouvez masquer le clavier lorsque vous touchez l'extérieur

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.