113 votes

PopupWindow - Dismiss en cas de clic à l'extérieur

J'ai une PopupWindow sur mon activité, le problème est que ma PopupWindow s'affiche toujours même lorsque j'interagis avec mon activité (par exemple en faisant défiler ma liste). Je peux faire défiler ma liste et la PopupWindow est toujours là.

Ce que je veux réaliser, c'est que lorsque je touche/fait défiler/clique/etc sur l'écran qui n'est pas la PopupWindow, je veux faire disparaître la PopupWindow. Tout comme le fonctionnement d'un menu. Si vous cliquez en dehors du menu, le menu sera rejeté.

J'ai essayé setOutsideTouchable(true) mais la fenêtre ne se fermera pas. Merci.

142voto

mpellegr Points 602

J'ai constaté 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 aussi. Voici la partie qui fonctionne pour moi :

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

Alternativement :

myPopupWindow.setFocusable(true);

Je ne suis pas sûr des différences, mais le code source de ListPopupWindow utilise effectivement cette dernière lorsque sa modalité est définie sur true avec setModal, donc au moins les développeurs d'Android considèrent cette approche viable, et elle ne fait qu'une ligne.

6 votes

Merci beaucoup. Aucune des autres réponses n'a fonctionné pour moi ou ne l'a expliqué suffisamment bien. La deuxième option ne fonctionne pas pour moi cependant.

2 votes

Je note également que BitmapDrawable est déprécié. Ce serait bien d'avoir une vraie solution au problème, car ces solutions ressemblent à des palliatifs temporaires dont le support n'est pas garanti dans les nouvelles versions de l'API.

1 votes

Pour ne pas utiliser le constructeur déprécié de BitmapDrawable, voir ici : stackoverflow.com/a/21680637/2048266 . popupWindow.setBackgroundDrawable(new BitmapDrawable(getResources(), ""))) ;

139voto

Marcin S. Points 5141

Veuillez essayer de régler setBackgroundDrawable sur PopupWindow qui devrait fermer la fenêtre si vous touchez à l'extérieur de celle-ci.

0 votes

Mais ce n'est pas un dialogue, c'est une PopupWindow.

5 votes

Je l'ai manqué. Utilisez-vous setBackgroundDrawable sur votre popupWindow ? Je sais que le fait de mettre le dessinable d'arrière-plan à null tue le OnTouchListener.

0 votes

Vous l'avez. Le réglage du backgroundDrawable fonctionne. Vous devriez modifier votre réponse, pour que je puisse la marquer comme acceptée :) Merci mon pote.

25voto

Marcin S. Points 5141

Je sais qu'il est tard mais je remarque que les gens ont toujours un problème avec la fenêtre popup. J'ai décidé d'écrire un exemple entièrement fonctionnel où vous pouvez renvoyer la fenêtre popup 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 de la fenêtre popup : 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 mise en page de l'activité en cours dans laquelle la popupWindow apparaîtra.

1 votes

Merci - cela a fonctionné pour moi. Juste une petite note est d'utiliser plutôt un autre nom que PopupWindow pour votre classe personnalisée, peut-être l'appeler MyPopupWindow au lieu de Popupwindow afin qu'Android ne soit pas confondu entre sa classe Android standard et votre classe personnalisée.

0 votes

@Marcin S. findViewById(R.id.YOUR_MAIN_LAYOUT) ? ? Est-ce que ce sera R.layout.My_Layout

0 votes

@Simon findViewById(R.id.YOUR_MAIN_LAYOUT) ? ? Est-ce que ce sera R.layout.My_Layout ?

5voto

MuhammadAamirALi Points 2555
mPopWindow.setFocusable(true);

1 votes

C'est la seule chose nécessaire. Je ne comprends pas pourquoi la réponse acceptée est si fortement upvoted.

3voto

amak Points 33

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

PopupWindow.getBackground().setAlpha(0);

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

1 votes

GetBackground() pourrait être nul.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X