Удаление всплывающего окна Android - PullRequest
60 голосов
/ 26 июня 2010

У меня есть всплывающее окно, которое отображается, когда я щелкаю элемент в своем списке действий. Проблема в том, что клавиша возврата не закрывает его. Я попытался поймать клавишу возврата в списке действий, но он не регистрируется ... затем я попытался зарегистрировать onkeylistener для представления, которое я передаю во всплывающее окно. Как это:

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

Но этот слушатель тоже не стреляет. Вы можете мне помочь? У меня нет идей :) 1007 *

Ответы [ 10 ]

148 голосов
/ 26 июня 2010

Это потому, что всплывающее окно не реагирует на события onTouch или onKey, если у него нет фона! = Null. Посмотрите код, который я написал , чтобы помочь с этим.В базовом случае вы можете позвонить PopupWindow#setBackgroundDrawable(new BitmapDrawable()), чтобы заставить его действовать так, как вы ожидаете.Вам не понадобится ваш собственный слушатель onKey.Вам также может понадобиться позвонить PopupWindow#setOutsideTouchable(true), если вы хотите, чтобы он исчез, когда пользователь щелкает за пределами окна.

Расширенный эзотерический ответ:

Причина, по которой фон не может быть нулевым, заключается в том, что происходит в PopupWindow#preparePopup.Если он обнаруживает background != null, он создает экземпляр PopupViewContainer и вызывает для него setBackgroundDrawable и помещает в него представление вашего контента.PopupViewContainer - это, по сути, FrameLayout, который прослушивает сенсорные события и KeyEvent.KEYCODE_BACK, чтобы закрыть окно.Если background == null, он ничего не делает, а просто использует ваш контент.В качестве альтернативы зависимости от PopupWindow вы можете расширить свой корень ViewGroup, чтобы он вел себя так, как вы хотите.

36 голосов
/ 16 ноября 2011

Делайте так, как описано ниже:

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);
7 голосов
/ 26 августа 2014

Для новых проектов лучше использовать

popupWindow.setBackgroundDrawable(new ColorDrawable());

вместо

popupWindow.setBackgroundDrawable(new BitmapDrawable());

как BitmapDrawable устарела. Кроме того, в этом случае это лучше, чем ShapeDrawable. Я заметил, что когда PopupWindow представляет собой прямоугольник с закругленными углами, ShapeDrawable заполняет углы черным.

5 голосов
/ 08 ноября 2010

Действительно простое решение - написать pw.setFocusable (true), но, вероятно, вы не хотите этого делать, потому что тогда MapActivity не будет обрабатывать сенсорные события.

Лучшее решение - переопределить клавишу возврата, например, так:

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

Удачи!

4 голосов
/ 27 мая 2014

просто используйте это

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

, которое не считается устаревшим.я бы избегал нового ShapeDrawable (), поскольку он будет медленно рендериться, поскольку он пытается нарисовать фигуру, когда экран должен быть перерисован.

4 голосов
/ 22 мая 2014

Для новых искателей , так как создание new BitmapDrawable сейчас не разрешено (The constructor BitmapDrawable() is deprecated), поэтому вам нужно изменить его на new ShapeDrawable(), чтобы вы могли изменить:

pw.setBackgroundDrawable(new BitmapDrawable());

Кому:

pw.setBackgroundDrawable(new ShapeDrawable());

И вся работа будет выглядеть так:

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);
3 голосов
/ 18 ноября 2011

Надеюсь, это поможет вам

 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;
        }
    });
1 голос
/ 13 марта 2015

вам нужно добавить setBackgroundDrawable(new BitmapDrawable()) для вашего PopupWindow.

0 голосов
/ 28 декабря 2018
pw.setBackgroundDrawable(new ColorDrawable());  

должен написать это до setContentView

Это работает для меня.

0 голосов
/ 22 августа 2013
    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+"");

        }
    });
}

Эта проблема - всплывающее окно. Удачи

...