2011-08-27 19 views
37

Mi stavo chiedendo se è possibile in qualche modo toccare fuori una finestra di dialogo popup (o un'attività con un tema di dialogo) e chiuderla semplicemente toccando al di fuori di essa?Toccare fuori dalla finestra di dialogo Android per chiuderla?

Ho fatto una foto veloce per illustrarlo:

enter image description here

Normalmente, è necessario premere il tasto di nuovo per chiudere le finestre di dialogo, ma su Honeycomb potrebbe essere bello avere la possibilità di appena intercettazioni al di fuori della finestra di dialogo, a causa di tutte le proprietà dello schermo.

+1

Credo eliminabili è il comportamento di default - almeno per un'attività con un tema di dialogo. –

risposta

47

La mia app è una singola attività con Theme.Holo.Dialog. Nel mio caso l'altra risposta non ha funzionato. Ha solo reso le altre app in background o la schermata di avvio per ricevere eventi touch.

Ho trovato che l'utilizzo di dispatchTouchEvent funziona nel mio caso. Penso che sia anche una soluzione più semplice. Ecco alcuni esempi di codice su come usarlo per rilevare rubinetti di fuori l'attività con un tema di dialogo:

@Override 
public boolean dispatchTouchEvent(MotionEvent ev) { 
    Rect dialogBounds = new Rect(); 
    getWindow().getDecorView().getHitRect(dialogBounds); 

    if (!dialogBounds.contains((int) ev.getX(), (int) ev.getY())) { 
     // Tapped outside so we finish the activity 
     this.finish(); 
    } 
    return super.dispatchTouchEvent(ev); 
} 
+12

Funziona meglio se si modifica la condizione if in 'if (! DialogBounds.contains ((int) event.getX(), (int) event.getY()) && event.getAction() == MotionEvent.ACTION_DOWN)' In questo modo non si chiude se l'utente sposta accidentalmente il dito all'esterno di "Attività". – Glitch

+0

Questo è geniale, Glitch - grazie mille. –

+1

Utilizzo dell'API di livello 8, Utilizzo di un'attività con tema 'android: Theme.Dialog' e con questo codice:' dialogBounds.top' e 'dialogBounds.left' hanno il valore 0; e 'dialogBounds.bottom' e' dialogBounds.right' hanno i valori della dimensione dello schermo, suggerendo che la finestra diolog è in realtà assunta come schermo intero. Quindi non posso mettere questo codice al lavoro. Altre idee per cui questo sta accadendo? – Jorge

14

C'è un metodo TouchInterceptor che vi chiama quando si sfiora fuori dal lato della finestra popup

Per esempio

mWindow.setTouchInterceptor(new OnTouchListener() { 
      @Override 
      public boolean onTouch(View v, MotionEvent event) { 
       if (event.getAction() == MotionEvent.ACTION_OUTSIDE) { 
        mWindow.dismiss(); 

        return true; 
       } 

       return false; 
      } 
     }); 

mWindow è la finestra pop-up

e se si vuole stessa funzionalità per Attività devi seguire i passaggi seguenti.

1) Aggiungere bandiera, prima setContentView() metodo chiamato in onCreate();

getWindow().setFlags(LayoutParams.FLAG_NOT_TOUCH_MODAL, LayoutParams.FLAG_NOT_TOUCH_MODAL); 

    // ...but notify us that it happened. 
    getWindow().setFlags(LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH); 

2) Override onTouchEvent() evento in attività

e scrittura sottostante Codice

@Override 
     public boolean onTouchEvent(MotionEvent event) { 
      if (event.getAction() == MotionEvent.ACTION_OUTSIDE) { 
       Toast.makeText(getApplicationContext(), "Finish", 3000).show(); 
       finish();    
       return true; 
      } 
      return false; 
     } 

La copia completa è qui

Attività

package net.londatiga.android; 

import android.app.Activity; 
import android.os.Bundle; 

import android.view.MotionEvent; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.view.View.OnTouchListener; 
import android.view.WindowManager.LayoutParams; 

import android.widget.Button; 
import android.widget.Toast; 

public class NewQuickAction3DActivity extends Activity implements OnTouchListener { 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     // Make us non-modal, so that others can receive touch events. 
     getWindow().setFlags(LayoutParams.FLAG_NOT_TOUCH_MODAL, LayoutParams.FLAG_NOT_TOUCH_MODAL); 

     // ...but notify us that it happened. 
     getWindow().setFlags(LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH); 

     setContentView(R.layout.main); 

    } 


    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
     if (event.getAction() == MotionEvent.ACTION_OUTSIDE) { 
      Toast.makeText(getApplicationContext(), "Hi", 3000).show(); 

      return true; 
     } 

     return false; 
    } 
} 

Questo è manifest.xml

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
     package="net.londatiga.android" 
     android:versionCode="1" 
     android:versionName="1.0"> 
    <uses-sdk android:minSdkVersion="7" /> 

    <application android:icon="@drawable/icon" android:label="@string/app_name"> 
     <activity android:name=".NewQuickAction3DActivity" 
        android:label="@string/app_name" android:theme="@android:style/Theme.Holo.Dialog"> 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 
       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 

    </application> 
</manifest> 
+2

Questo è solo per 'PopupWindow', giusto? Sto utilizzando un'attività standard con il tema Theme.Holo.Dialog in Honeycomb. –

+0

Ho modificato la mia risposta, controlla – Dharmendra

+0

Sì, l'ho provato prima che tu lo scrivessi, ma non ha funzionato neanche :(Manca un punto e virgola alla fine() btw :) –

89
dialog.setCanceledOnTouchOutside(true) 

Imposta se questa finestra viene annullata quando viene toccato al di fuori dai limiti della finestra.

+2

Questa è la soluzione migliore ... Così semplice. Perché non è questa la risposta? –

+1

Avevo bisogno che funzionasse su un'attività con il tema della finestra di dialogo, e in tal caso non funzionerebbe, ma l'ho messo in circolazione per le finestre di dialogo generali. –

+3

'this.setFinishOnTouchOutside (false);' funziona per un'attività di dialogo – Nick

5

È possibile utilizzare anche Activity#setFinishOnTouchOutside se la finestra di dialogo è Activity. Questo deve essere il modo più breve per Activity s;)

(È API 11+, tuttavia, l'API < = 10 è generalmente la dimensione dello schermo normale.)

+0

Questa è la risposta vincente, la domanda è indirizzata Attività a tema come finestre di dialogo, non i dialoghi. – JaredBanyard

1

vecchia questione, ma un'altra soluzione:

  1. Fai la tua attività di primo piano a schermo intero. Layout Usenested: il layout a schermo intero dovrebbe avere uno sfondo trasparente (ad esempio @null o @android:color/transparent). Il layout interno dovrebbe avere uno sfondo visibile.

  2. Aggiungere uno OnClickListener al layout esterno invisibile che finish() es l'attività.

0

Qualsiasi visualizzazione all'interno della finestra di dialogo può impostare di consumare l'evento di tocco in modo che di seguito non venga chiamato.

onCreate(){ 
    getWindow().getDecorView().getRootView().setOnTouchListener(new OnTouchListener(){ 
     @Override 
     public boolean onTouch(View v, MotionEvent event) { 
      dialog.dismiss(); 
      return false; 
     } 
    }); 
0
LayoutParams lp=dialogp.getWindow().getAttributes(); 
lp.flags=LayoutParams.FLAG_LAYOUT_NO_LIMITS; 

ho aggiunto questo e funziona senza problemi su 3.0, ma dovrebbe funzionare su tutti.

1

Utilizzare lo stile del dialogo piuttosto che altri stili.

Ad esempio, utilizzare

public YourCustomDialog(Context context) { 
    super(context, android.R.style.Theme_Holo_dialog_NoActionBar); 
} 

quando si utilizzano altri stili come Theme_Translucent_NoTitleBar, la finestra di dialogo non saranno licenziati.

5

È possibile utilizzare

dialog.setCancelable(true\false); 

Per la più recente vesrions di Android;

Disabilita l'evento outSideTouching.

+0

Quali versioni? – AbleArcher

+0

È testato per tutte le versioni tranne KITKAT :) – Amt87

3
dialog = new Dialog(MainActivity.this); 
    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); 
    dialog.setContentView(R.layout.dialog_layout); 
    dialog.getWindow().setBackgroundDrawableResource(
      android.R.color.transparent); 
    dialog.setCancelable(false); 

    dialog.setCanceledOnTouchOutside(true); 

Verificare se si dispone di questa riga di codice o no ....

dialog.setCanceledOnTouchOutside(true); 
4

Semplicemente scrivo dialog.setCanceledOnTouchOutside (false); e funziona per me, la finestra non verrà ignorata al di fuori toccare.

1

this.setFinishOnTouchOutside (false);

si può usare questo

Problemi correlati