Увольнение всплывающего окна Android

У меня появляется всплывающее окно, когда я нажимаю элемент в моем списке. Проблема в том, что задний ключ не закрывает его. Я попытался поймать задний ключ в моей активности в списке, но он не зарегистрировал его... тогда я попытался зарегистрировать 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);

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

Ответ 1

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

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

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

Ответ 2

Сделайте так, чтобы он работал нормально:

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

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

popupWindow.setBackgroundDrawable(new ColorDrawable());

вместо

popupWindow.setBackgroundDrawable(new BitmapDrawable());

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

Ответ 4

На самом деле простым решением является запись 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);
} 

Удачи!

Ответ 5

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

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

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

Ответ 6

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

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

Ответ 7

Для новых поисковиков, поскольку создание 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);

Ответ 8

вам нужно добавить setBackgroundDrawable(new BitmapDrawable()) для 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+"");

        }
    });
}

Эта проблема - popupwindow 底层 的 消息 机制 决定 的, 因为 它 是 阻塞 式 的. Хорошая удача