63 votes

Renvoi d'une fenêtre popup Android

J'ai une fenêtre popup qui s'affiche lorsque je clique sur un élément de mon activité de liste. Le problème est que la touche retour ne la ferme pas. J'ai essayé d'attraper la touche retour dans mon activité de liste mais elle ne l'enregistre pas... puis j'ai essayé d'enregistrer un onkeylistener à la vue que je passe à ma fenêtre popup. Comme ceci :

pop.setOnKeyListener(new View.OnKeyListener() {

        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            // TODO Auto-generated method stub
            boolean res=false;
            if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
                // do something on back.
                Log.e("keydown","back");
                if (pw.isShowing()) {
                    Log.e("keydown","pw showing");
                    pw.dismiss();
                    res = true;
                }
            } else {
                res = false;
            }
            return res;
        }
    });

qui est passé à une popup comme ceci :

pw = new PopupWindow(
       pop, 
       240, 
       70, 
       true);

Mais cet auditeur ne tire pas non plus. Pouvez-vous m'aider ? Je suis à court d'idées :)

0 votes

Oui, mais la fenêtre popup contient des images cliquables...

150voto

Qberticus Points 20157

En effet, la fenêtre popup ne répond pas aux événements onTouch ou onKey, sauf si son arrière-plan est != null. Regardez un peu le code que j'ai écrit pour vous aider. Dans le cas de base, vous pouvez appeler PopupWindow#setBackgroundDrawable(new BitmapDrawable()) pour le forcer à agir comme vous le souhaitez. Vous n'aurez pas besoin de votre propre écouteur onKey. Vous pouvez également avoir besoin d'appeler PopupWindow#setOutsideTouchable(true) si vous voulez qu'elle disparaisse lorsque l'utilisateur clique en dehors des limites de la fenêtre.

Réponse ésotérique étendue :

La raison pour laquelle l'arrière-plan ne peut pas être nul est à cause de ce qui se passe dans PopupWindow#preparePopup . S'il détecte background != null il crée une instance de PopupViewContainer et appelle setBackgroundDrawable sur ça et met votre vue de contenu dedans. PopupViewContainer est essentiellement un FrameLayout qui écoute les événements liés au toucher et le KeyEvent.KEYCODE_BACK pour fermer la fenêtre. Si background == null, il ne fait rien de tout cela et utilise simplement votre vue de contenu. Vous pouvez, au lieu de dépendre de PopupWindow pour gérer cela, étendez votre racine ViewGroup pour se comporter comme vous le souhaitez.

0 votes

J'ai un problème très similaire. Mon CustomView, qui est transmis à la PopupWindow, n'enregistre pas les événements onKeyDown(), mais il enregistre l'événement onTouchEvent().

11 votes

Assurez-vous que vous appelez setBackgroundDrawable avant d'afficher la boîte de dialogue... j'ai mis du temps à le comprendre.

2 votes

Puis-je demander comment avez-vous découvert ça ? Pour moi, c'est juste impossible à deviner, donc soit vous avez accès à quelques documentation cachée ou vous êtes un magicien :)

39voto

ParmarS Points 501

Faites comme indiqué ci-dessous, cela fonctionne bien :

PopupWindow pw;
LayoutInflater inflater = (LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.weight_popup, (ViewGroup)findViewById(R.id.linlay_weight_popup));
pw = new PopupWindow(layout,LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT, true);
pw.setBackgroundDrawable(new BitmapDrawable());
pw.setOutsideTouchable(true);
pw.showAsDropDown(btnSelectWeight);

5voto

Vanja Points 615

Une solution très simple consiste à écrire pw.setFocusable(true), mais il est probable que vous ne souhaitiez pas le faire, car alors l'activité MapActivity ne gérera pas les événements tactiles.

Une meilleure solution est de remplacer la touche arrière, par exemple comme ceci :

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {

    // Override back button
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        if (pw.isShowing()) {
            pw.dismiss();
            return false;
        }
    }
    return super.onKeyDown(keyCode, event);
} 

Bonne chance !

4voto

j2emanue Points 3456

Utilisez simplement ceci

mPopupWindow.setBackgroundDrawable(new BitmapDrawable(null,""));

qui n'est pas déprécié. J'éviterais new ShapeDrawable() car il va rendre lentement car il essaie de dessiner une forme lorsque l'écran doit être redessiné.

3voto

Dwivedi Ji Points 2895

J'espère que cela vous aidera

 pw.setTouchInterceptor(new View.OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            // TODO Auto-generated method stub
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                pw.dismiss();
            }
            return true;
        }
    });

0 votes

Bonjour, est-ce indispensable lorsque l'on a affaire à une fenêtre popup ? Ou bien pw.setOutsideTouchable(true) ; est suffisant pour écarter la fenêtre popup lorsque nous cliquons à l'extérieur de celle-ci ?

0 votes

@GMsoF les deux sont indispensables, regardez ma réponse

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