Une fenêtre contextuelle s'affiche lorsque je clique sur un élément de l'activité de ma liste. Le problème est que la touche back ne la ferme pas. J'ai essayé de saisir la clé de retour dans mon activité de liste, mais cela ne l'a pas enregistrée ... puis j'ai essayé d'enregistrer un onkeylistener dans la vue que je passe à ma fenêtre contextuelle. Comme ça:
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é à un 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 :)
En effet, la fenêtre contextuelle ne répond pas aux événements onTouch ou onKey sauf si son arrière-plan est! = Null. Découvrez le code que j'ai écrit pour aider avec cela. 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 auditeur onKey. Vous devrez peut-être également appeler PopupWindow#setOutsideTouchable(true)
si vous souhaitez que le message 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 null est due à ce qui se passe dans PopupWindow#preparePopup
. S'il détecte background != null
, il crée une instance de PopupViewContainer
et appelle setBackgroundDrawable
sur celle-ci et y place votre vue du contenu. PopupViewContainer
est fondamentalement une FrameLayout
qui écoute les événements tactiles et l'événement KeyEvent.KEYCODE_BACK
pour fermer la fenêtre. Si background == null, il ne fait rien de tout cela et utilise simplement votre vue du contenu. Vous pouvez, au lieu de dépendre de PopupWindow
pour gérer cela, étendre votre racine ViewGroup
pour qu'elle se comporte comme vous le souhaitez.
Faites comme suit cela fonctionne très 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);
Pour les nouveaux projets, il vaut mieux utiliser
popupWindow.setBackgroundDrawable(new ColorDrawable());
au lieu de
popupWindow.setBackgroundDrawable(new BitmapDrawable());
comme BitmapDrawable est obsolète. Aussi, c'est mieux que ShapeDrawable dans ce cas. J'ai remarqué que lorsque PopupWindow est un rectangle aux coins arrondis, ShapeDrawable remplit les coins en noir.
Une solution très simple consiste à écrire pw.setFocusable (true), mais vous ne voulez probablement pas le faire car, dans ce cas, MapActivity ne gérera pas les événements tactiles.
Une meilleure solution consiste à remplacer la touche Retour, 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!
Pour les nouveaux chercheurs , la création d'un new BitmapDrawable
n'est pas autorisée maintenant (The constructor BitmapDrawable() is deprecated
), de sorte que vous devez le changer en new ShapeDrawable()
pour que vous changiez:
pw.setBackgroundDrawable(new BitmapDrawable());
À :
pw.setBackgroundDrawable(new ShapeDrawable());
Et tout le travail sera comme:
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.WRAP_CONTENT,LayoutParams.WRAP_CONTENT, true);
pw.setOutsideTouchable(true);
pw.setBackgroundDrawable(new ShapeDrawable());
pw.setTouchInterceptor(new OnTouchListener() { // or whatever you want
@Override
public boolean onTouch(View v, MotionEvent event)
{
if(event.getAction() == MotionEvent.ACTION_OUTSIDE) // here I want to close the pw when clicking outside it but at all this is just an example of how it works and you can implement the onTouch() or the onKey() you want
{
pw.dismiss();
return true;
}
return false;
}
});
pw.showAtLocation(layout, Gravity.CENTER, 0, 0);
juste utiliser ceci
mPopupWindow.setBackgroundDrawable(new BitmapDrawable(null,""));
qui n'est pas obsolète. J'éviterais la nouvelle forme ShapeDrawable () car son rendu sera lent alors qu'il tente de dessiner une forme lorsque l'écran doit être redessiné.
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;
}
});
vous devez ajouter setBackgroundDrawable(new BitmapDrawable())
pour votre PopupWindow
.
pw.setBackgroundDrawable(new ColorDrawable());
doit l'écrire avant setContentView
Cela fonctionne pour moi.
private void initPopupWindow() {
// TODO Auto-generated method stub
View view = getLayoutInflater().inflate(R.layout.main_choice, null);
ListView main_menu_listview = (ListView) view.findViewById(R.id.main_menu_listview);
ShowMainChoice madapter = new ShowMainChoice(context);
main_menu_listview.setAdapter(madapter);
int width = (int)getWindowManager().getDefaultDisplay().getWidth()/2;
popupWindow = new PopupWindow(view, width,WindowManager.LayoutParams.WRAP_CONTENT);
popupWindow.setBackgroundDrawable(new BitmapDrawable());//this is important,如果缺少这句将导致其他任何控件及监听都得不到响应
popupWindow.setOutsideTouchable(true);
popupWindow.setFocusable(true);
main_menu_listview.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {
// TODO Auto-generated method stub
Log.e("++++++>", arg2+"");
}
});
}
Ce problème est popupwindow! Bonne chance!