2010-06-25 11 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

Да, но всплывающее окно содержит интерактивные изображения ... – Bostjan

ответ

144

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

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

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

+0

у меня очень похожая проблема. Моя CustomView, которая передается PopupWindow не регистрирует OnKeyDown() события, но это не регистрирует onTouchEvent() . – znq

+10

убедитесь, что вы звоните setBackgroundDrawable перед показом т Диалог он ... взял меня некоторое время, чтобы понять, что один из. – DallinDyer

+2

Могу ли я спросить, как ** ** вы узнали это? Для меня, это просто невозможно угадать, так как у вас есть доступ к некоторым * скрытой документации * или волшебник :) – Raffaele

5

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

удачи!

35

ли согласно следующим она отлично работает:

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

Я надеюсь, что это будет помощь для вас

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

+0

@GMsoF оба должны, посмотрите на мой ответ –

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

     } 
    }); 
} 

Эта проблема popupwindow основное решение обмена сообщениями, потому что это блокировка. Успехи

4

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

pw.setBackgroundDrawable(new BitmapDrawable()); 

To:

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

просто использовать этот

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

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

6

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

popupWindow.setBackgroundDrawable(new ColorDrawable()); 

вместо

popupWindow.setBackgroundDrawable(new BitmapDrawable()); 

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

1

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

Смежные вопросы