可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have a popup window displaying when I click an item in my list activity. The problem is that the back key doesn\'t close it. I tried catching the back key in my list activity but it doesn\'t register it...then I tried registering a onkeylistener to the view I\'m passing to my popup window. Like this:
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;
}
});
which is passed to a popup like this:
pw = new PopupWindow(
pop,
240,
70,
true);
But that listener doesn\'t fire neither. Can you help me? I\'m out of ideas :)
回答1:
This is because the popup window does not respond to onTouch or onKey events unless it has a background that != null. Check out some code I wrote to help with this. In the basic case you can to call PopupWindow#setBackgroundDrawable(new BitmapDrawable())
to force it to act the way you expect. You won\'t need your own onKey listener. You might also need to call PopupWindow#setOutsideTouchable(true)
if you want it to go away when the user clicks outside of the window boundaries.
Extended esoteric answer:
The reason the background cannot be null is because of what happens in PopupWindow#preparePopup
. If it detects background != null
it creates an instance of PopupViewContainer
and calls setBackgroundDrawable
on that and puts your content view in it. PopupViewContainer
is basically a FrameLayout
that listens for touch events and the KeyEvent.KEYCODE_BACK
event to dismiss the window. If background == null, it doesn\'t do any of that and just uses your content view. You can, as an alternative to depending on PopupWindow
to handle that, extend your root ViewGroup
to behave the way you want.
回答2:
Do as per following it works fine:
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);
回答3:
For new projects it\'s better to use
popupWindow.setBackgroundDrawable(new ColorDrawable());
instead of
popupWindow.setBackgroundDrawable(new BitmapDrawable());
as BitmapDrawable is deprecated. Also, it\'s better than ShapeDrawable in this case. I noticed that when PopupWindow is a rectangle with rounded corners, ShapeDrawable fills corners with black.
回答4:
A really simple solution is to write pw.setFocusable(true), but probably you don\'t want to do this because then the MapActivity won\'t handle touch events.
A better solution is to override the back key, e.g like this:
@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);
}
Good luck!
回答5:
For the new searchers, as creating a new BitmapDrawable
is not allowed now(The constructor BitmapDrawable() is deprecated
) , so that you have to change it to a new ShapeDrawable()
, so that you will change :
pw.setBackgroundDrawable(new BitmapDrawable());
To :
pw.setBackgroundDrawable(new ShapeDrawable());
And the whole work will be like :
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);
回答6:
just use this
mPopupWindow.setBackgroundDrawable(new BitmapDrawable(null,\"\"));
which is not deprecated. i\'d avoid new ShapeDrawable() as its going to render slowly as it tries to draw a shape when the screen needs to be redrawn.
回答7:
I hope this will be help for you
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;
}
});
回答8:
you need add setBackgroundDrawable(new BitmapDrawable())
for your PopupWindow
.
回答9:
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+\"\");
}
});
}
This problem is popupwindow底层的消息机制决定的,因为它是阻塞式的。Good luck
回答10:
pw.setBackgroundDrawable(new ColorDrawable());
must wrote it before setContentView
This works for me.