2010-06-25 134 views
59

我有一个弹出窗口显示,当我点击我的列表活动中的项目。问题是后退键没有关闭它。我尝试捕捉我的列表活动中的后退键,但它没有注册它...然后我试着将一个onkeylistener注册到我传递给我的弹出窗口的视图中。就像这样:Android弹出窗口解雇

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; 
     } 
    }); 

被传递到弹出这样的:

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

但是,听者不火都不是。你可以帮我吗?我不知道:)

+0

Yes, but the popup window contains clickable images... – Bostjan 2010-06-25 20:43:15

回答

144

这是因为弹出窗口不会响应onTouch或onKey事件,除非它具有!= null的背景。 Check out some code I wrote来帮助这一点。在基本情况下,您可以致电PopupWindow#setBackgroundDrawable(new BitmapDrawable())强制其按您期望的方式行事。你不需要你自己的onKey监听器。如果您希望在用户单击窗口边界之外时单击此选项,则可能还需要拨打PopupWindow#setOutsideTouchable(true)

扩展深奥的答案:

背景不能为空的原因是因为在PopupWindow#preparePopup会发生什么。如果它检测到background != null,它将创建一个PopupViewContainer的实例,并调用setBackgroundDrawable,并将其放入内容视图中。 PopupViewContainer基本上是一个FrameLayout,它侦听触摸事件和KeyEvent.KEYCODE_BACK事件来关闭该窗口。如果background == null,它不会执行任何操作,只是使用您的内容视图。您可以选择取决于PopupWindow来处理该问题,请将您的根ViewGroup扩展为您想要的方式。

+0

I have a very similar problem. My CustomView, which is passed to the PopupWindow doesn't register onKeyDown() events, but it does register the onTouchEvent(). – znq 2010-10-19 15:49:47

+10

make sure you call setBackgroundDrawable before showing the dialog... took me awhile to figure that one out. – DallinDyer 2011-09-28 06:06:00

+2

May I ask **how** did you discover this? To me, it's just impossible to guess, so either you have access to some *hidden documentation* or you are a wizard :) – Raffaele 2012-10-11 22:23:15

5

一个非常简单的解决方案是编写pw.setFocusable(true),但可能你不想这样做,因为MapActivity不会处理触摸事件。

更好的解决方案是重写返回键,e.g这样的:

@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); 
} 

祝你好运!

35

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

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; 
     } 
    }); 
+0

嗨,我们正在处理弹出窗口时,这是必须的吗?或者pw.setOutsideTouchable(true);当我们点击弹出窗口之外时,足以解除弹出窗口? – GMsoF 2012-11-08 09:45:09

+0

@GMsoF都是必须的,看看我的答案 – 2014-05-22 09:14:49

0
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

4

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); 
4

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.

6

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.

1

you need add setBackgroundDrawable(new BitmapDrawable()) for your PopupWindow .