2010-06-25 8 views
59

Ho una finestra popup che viene visualizzata quando faccio clic su un elemento nella mia attività di elenco. Il problema è che il tasto indietro non lo chiude. Ho provato a prendere il tasto indietro nella mia attività di lista ma non lo registra ... poi ho provato a registrare un onkeylistener alla vista che sto passando alla mia finestra popup. Come questo:Chiusura finestra popup 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; 
     } 
    }); 

che è passato ad un popup come questo:

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

Ma questo ascoltatore non si attiva nessuno dei due. Mi potete aiutare? Sono fuori di idee :)

+0

Sì, ma la finestra a comparsa contiene le immagini cliccabili ... – Bostjan

risposta

144

Questo perché la finestra popup non risponde agli eventi onTouch o onKey a meno che non abbia uno sfondo che! = Null. Check out some code I wrote per aiutare con questo. Nel caso base puoi chiamare PopupWindow#setBackgroundDrawable(new BitmapDrawable()) per costringerlo ad agire come ti aspetti. Non avrai bisogno del tuo ascoltatore onKey. Potrebbe anche essere necessario chiamare PopupWindow#setOutsideTouchable(true) se si desidera che si spenga quando l'utente fa clic all'esterno dei limiti della finestra.

estesa risposta esoterica:

Il motivo lo sfondo non può essere nullo a causa di ciò che accade in PopupWindow#preparePopup. Se rileva background != null crea un'istanza di PopupViewContainer e chiama lo setBackgroundDrawable su quello e inserisce la visualizzazione del contenuto in esso. PopupViewContainer è fondamentalmente un FrameLayout che ascolta gli eventi di tocco e l'evento KeyEvent.KEYCODE_BACK per chiudere la finestra. Se background == null, non lo fa e utilizza solo la vista del contenuto. È possibile, in alternativa a dipendere da PopupWindow per gestirlo, estendere il root ViewGroup per comportarsi nel modo desiderato.

+0

ho un problema molto simile. la mia CustomView, che è passato al PopupWindow non registra onKeyDown() eventi, ma lo fa registrare l'onTouchEvent() . – znq

+10

assicuratevi di chiamare prima di mostrare setBackgroundDrawable t a finestra di dialogo ... mi ha portato un po 'per capire che uno. – DallinDyer

+2

Posso chiedere ** ** come hai scoperto questo? Per me, è solo impossibile indovinare, quindi o si ha accesso ad alcuni * documentazione nascosto * o sono un mago :) – Raffaele

5

Una soluzione davvero semplice è scrivere pw.setFocusable (true), ma probabilmente non si vuole farlo perché quindi MapActivity non gestirà gli eventi touch.

Una soluzione migliore è quella di ignorare la chiave, per esempio come questo:

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

Buona fortuna!

35

fare secondo il seguente funziona bene:

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

Spero che questo sarà di aiuto per voi

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

Ciao, è un must quando abbiamo a che fare con la finestra popup? Oppure pw.setOutsideTouchable (true); è sufficiente per chiudere la finestra popup quando facciamo clic al di fuori della finestra popup? – GMsoF

+0

@GMsoF entrambi devono, guarda la mia risposta –

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

     } 
    }); 
} 

Questo problema è PopupWindow decisione di messaggistica sottostante, perché è il blocco di. Buona fortuna

4

Per i nuovi ricercatori, come la creazione di un new BitmapDrawable non è permesso ora (The constructor BitmapDrawable() is deprecated), in modo da avere per cambiarlo in un new ShapeDrawable(), in modo che si cambia:

pw.setBackgroundDrawable(new BitmapDrawable()); 

A:

pw.setBackgroundDrawable(new ShapeDrawable()); 

E tutta l'opera sarà come:

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

basta usare questo

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

che non è deprecato. Eviterei nuova ShapeDrawable() come la sua intenzione di rendere lentamente in quanto cerca di disegnare una forma quando lo schermo ha bisogno di essere ridisegnato .

6

per i nuovi progetti è meglio usare

popupWindow.setBackgroundDrawable(new ColorDrawable()); 

invece di

popupWindow.setBackgroundDrawable(new BitmapDrawable()); 

come è deprecato BitmapDrawable. Inoltre, è meglio che ShapeDrawable in questo caso. Ho notato che quando PopupWindow è un rettangolo con gli angoli arrotondati, ShapeDrawable riempie gli angoli con il nero.

1

dovete aggiungere setBackgroundDrawable(new BitmapDrawable()) per il vostro PopupWindow .