web-dev-qa-db-fra.com

PopupWindow - Ignore quand on clique à l'extérieur

J'ai une PopupWindow sur mon activité, le fait est que ma PopupWindow s'affiche même lorsque j'interagis avec mon activité (par exemple, le défilement de ma liste). Je peux faire défiler ma liste et la fenêtre Popup est toujours là.

Ce que je veux réaliser, c’est que lorsque je touche/défile/clique sur/etc sur l’écran qui n’est pas la Fenêtre Popup, je veux fermer la Fenêtre Popup. Juste comme fonctionne un menu. Si vous avez cliqué en dehors du menu, le menu sera fermé.

J'ai essayé setOutsideTouchable(true) mais la fenêtre ne sera pas ignorée. Merci.

75
lorraine

Essayez de définir setBackgroundDrawable sur PopupWindow qui devrait fermer la fenêtre si vous touchez en dehors de celle-ci.

117
Marcin S.

J'ai trouvé qu'aucune des réponses fournies ne fonctionnait pour moi, à l'exception du commentaire de WareNinja sur la réponse acceptée, et celle de Marcin S. fonctionnera probablement également. Voici la partie qui fonctionne pour moi:

myPopupWindow.setBackgroundDrawable(new BitmapDrawable());
myPopupWindow.setOutsideTouchable(true);

Alternativement:

myPopupWindow.setFocusable(true);

Vous ne savez pas exactement quelles sont les différences, mais le code source de ListPopupWindow utilise en réalité ce dernier lorsque sa modalité est définie sur true avec setModal, de sorte qu'au moins les développeurs Android considèrent cette approche comme viable et qu'il ne s'agit que d'une ligne.

109
mpellegr

J'ai rencontré les mêmes problèmes, et corrigé comme ci-dessous les codes. Ça fonctionne bien pour moi.

    // Closes the popup window when touch outside.
    mPopupWindow.setOutsideTouchable(true);
    mPopupWindow.setFocusable(true);
    // Removes default background.
    mPopupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));

BTW, ne pas utiliser le constructeur obsolète BitmapDrawable, utilisez cenew ColorDrawable (Android.R.color.transparent)pour remplacer l'arrière-plan par défaut. 

S'amuser@.@

48
Luna Kong

Je sais qu'il est tard, mais je remarque que les gens ont toujours un problème avec la fenêtre contextuelle. J'ai décidé d'écrire un exemple totalement fonctionnel dans lequel vous pouvez fermer la fenêtre contextuelle en touchant ou en cliquant à l'extérieur de celle-ci ou en touchant simplement la fenêtre elle-même. Pour ce faire, créez une nouvelle classe PopupWindow et copiez ce code:

PopupWindow.class

public class PopupWindow extends Android.widget.PopupWindow
{
Context ctx;
Button btnDismiss;
TextView lblText;
View popupView;

public PopupWindow(Context context)
{
    super(context);

    ctx = context;
    popupView = LayoutInflater.from(context).inflate(R.layout.popup, null);
    setContentView(popupView);

    btnDismiss = (Button)popupView.findViewById(R.id.btn_dismiss);
    lblText = (TextView)popupView.findViewById(R.id.text);

    setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
    setWidth(WindowManager.LayoutParams.WRAP_CONTENT);

    // Closes the popup window when touch outside of it - when looses focus
    setOutsideTouchable(true);
    setFocusable(true);

    // Removes default black background
    setBackgroundDrawable(new BitmapDrawable());

    btnDismiss.setOnClickListener(new Button.OnClickListener(){

        @Override
        public void onClick(View v) {


         dismiss();
        }});

    // Closes the popup window when touch it
/*     this.setTouchInterceptor(new View.OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {

            if (event.getAction() == MotionEvent.ACTION_MOVE) {
                dismiss();
            }
            return true;
        }
    }); */   
   } // End constructor

   // Attaches the view to its parent anchor-view at position x and y
   public void show(View anchor, int x, int y)
   {
      showAtLocation(anchor, Gravity.CENTER, x, y);
   }
}

Créez maintenant la mise en page pour la fenêtre contextuelle: popup.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout     
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:layout_margin="1dp"
    Android:orientation="vertical"
    Android:padding="10dp" >

<TextView 
    Android:id="@+id/text" 
    Android:layout_width="wrap_content" 
    Android:layout_height="wrap_content"  
    Android:gravity="center" 
    Android:padding="5dp" 
    Android:text="PopupWindow Example"
    Android:textColor="#000000" 
    Android:textSize="17sp" 
    Android:textStyle="italic" />

<FrameLayout
    Android:layout_width="match_parent" 
    Android:layout_height="wrap_content" 
    Android:layout_gravity="center_vertical">

    <Button
        Android:id="@+id/btn_dismiss" 
        style="?android:attr/buttonStyleSmall" 
        Android:layout_width="wrap_content" 
        Android:layout_height="wrap_content" 
        Android:text="Dismiss" 
        Android:visibility="gone" />

    <TextView
        Android:id="@+id/lbl_dismiss"
        Android:layout_width="fill_parent"
        Android:layout_height="wrap_content"
        Android:gravity="center"
        Android:text="Touch outside of this box to dismiss"
        Android:textColor="#ffffff"
        Android:textStyle="bold" />

</FrameLayout>      

Dans votre activité principale, créez une instance de la classe PopupWindow:

final PopupWindow popupWindow = new PopupWindow(this);
popupWindow.show(findViewById(R.id.YOUR_MAIN_LAYOUT), 0, -250);

où YOUR_MAIN_LAYOUT est la présentation de l'activité en cours dans laquelle popupWindow apparaîtra

20
Marcin S.

Merci pour la réponse de @LunaKong et la confirmation de @ HourGlass. Je ne veux pas faire un commentaire en double, mais simplement le rendre clair et concis.

// Closes the popup window when touch outside. This method was written informatively in Google's docs.
mPopupWindow.setOutsideTouchable(true);

// Set focus true to prevent a touch event to go to a below view (main layout), which works like a dialog with 'cancel' property => Try it! And you will know what I mean.
mPopupWindow.setFocusable(true);

// Removes default background.
mPopupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));

Mttdat.

8
Nguyen Tan Dat

Notez que pour annuler avec popupWindow.setOutsideTouchable(true), vous devez créer la largeur et la hauteur wrap_content comme ci-dessous:

PopupWindow popupWindow = new PopupWindow(
            G.layoutInflater.inflate(R.layout.lay_dialog_support, null, false),
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT, true);

popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
popupWindow.setOutsideTouchable(true);
popupWindow.setFocusable(true);
popupWindow.showAtLocation(view, Gravity.RIGHT, 0, 0);
6
Hadi Note

Pour une ListPopupWindow, définissez la fenêtre sur modale à l’affichage.

mListPopupWindow.setModal(true);

De cette façon, un clic en dehors de la ListPopupWindow le rejettera.

4
toobsco42

Définissez le fond de la fenêtre transparent:

PopupWindow.getBackground().setAlpha(0);

Après cela, définissez votre arrière-plan dans la mise en page. Fonctionne bien.

3
amak
mPopWindow.setFocusable(true);
3
Muhammad Aamir Ali

Le travail de suggestion de @LunaKong est comme un charme.

Mais configurer mPopupWindow.setFocusable (false). supprime le contact inutile nécessaire pour faire disparaître la fenêtre contextuelle. 

Par exemple: Considérons qu’une fenêtre contextuelle est visible à l’écran et que vous êtes sur le point de cliquer sur un bouton. Donc, dans ce cas, (si mpopwindow.setFocusable (true)) Lors du premier clic sur un bouton, popupwindow disparaîtra. Mais vous devez cliquer à nouveau pour que le bouton fonctionne. if ** (mpopwindwo.setFocusable (false) ** clic simple du bouton ferme la fenêtre contextuelle et déclenche le clic du bouton. J'espère que cela aidera. 

2
HourGlass

Dans certains cas, il n'est pas souhaitable de pouvoir mettre au point la fenêtre contextuelle (par exemple, vous ne voudrez peut-être pas qu'elle vole la mise au point dans une autre vue). 

Une autre approche consiste à utiliser un intercepteur tactile:

popupWindow.setOutsideTouchable(true);
popupWindow.setTouchInterceptor(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
            popupWindow.dismiss();
        }
        return false;
    }
});
1
dev.bmax
  popupWindow.setTouchable(true);
  popupWindow.setFocusable(true);
  popupWindow.showAtLocation(popupView, Gravity.CENTER, 0, 0);

La fenêtre PopupWindow disparaîtra lorsque vous cliquerez/toucherez à l'écran. Assurez-vous que vous avez défini focusable sur true avant showAtLocation.

1
android

Vous pouvez utiliser isOutsideTouchableOUisFocusable pour masquer la fenêtre contextuelle lorsque vous touchez l'extérieur

popupWindow.isOutsideTouchable = true // dismiss popupwindow when touch outside

popupWindow.isFocusable = true // dismiss popupwindow when touch outside AND when press back button

Note

  • Actuellement, après le test, je vois setBackgroundDrawablene pas nous aider à rejeter popupwindow

  • Si vous regardez le code de licenciement dans PopupWindow (PopupWindow->PopupDecorView->dispatchKeyEvent et PopupWindow->PopupDecorView->onTouchEvent). Vous verrez que lorsque vous appuierez sur le bouton Précédent, ils seront renvoyés sur ACTION_UP et lorsqu'ils toucheront à l'extérieur, ils seront exclus sur ACTION_UP ou ACTION_OUTSIDE.

0
Phan Van Linh

Utilisez View popupView pour fermer la popupWindow

`popupView.setOnClickListener(new View.OnClickListener() {
                   @Override
                   public void onClick(View view) {
                       popupWindow.dismiss();
                   }
               }); 

` Si vous utilisez cette option, vous pouvez également définir OnLinkListener sur n’importe quel bouton de la fenêtre popup.

0
Prabhat Kumar Singh