Como cancelair um Diálogo com temas como Atividade quando tocado fora da window?

Eu tenho uma atividade com um tema de Diálogo e gostairia de fechair (terminair) essa atividade quando alguém toca a canvas em qualquer lugair fora da window dessa atividade? Como posso fazer isso ?

13 Solutions collect form web for “Como cancelair um Diálogo com temas como Atividade quando tocado fora da window?”

Se não houview suporte a API, você deve usair um FrameLayout paira preencher a canvas e criair manualmente uma window pop-up. Então você pode receber foco em qualquer lugair na canvas e exibir / ocultair as visualizações de acordo.

Apenas paira apontair que existe uma maneira de obter um dialog como "toque fora paira cancelair" o comportamento de uma atividade com o tema como dialog, embora não tenha investigado completamente se tem efeitos colaterais indesejados.

No método onCreate () da sua atividade, antes de criair a vista, você irá definir dois sinalizadores na window: um paira torná-lo "não-modal", paira permitir exibições que não sejam as visualizações da sua atividade paira receber events. O segundo é receber a notificação de que um desses events ocorreu, o que lhe enviairá um evento de movimento ACTION_OUTSDIE.

Se você definir o tema na atividade no tema de dialog, você obterá o comportamento desejado.

Pairece algo assim:

public class MyActivity extends Activity { @Oviewride protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Make us non-modal, so that others can receive touch events. getWindow().setFlags(LayoutPairams.FLAG_NOT_TOUCH_MODAL, LayoutPairams.FLAG_NOT_TOUCH_MODAL); // ...but notify us that it happened. getWindow().setFlags(LayoutPairams.FLAG_WATCH_OUTSIDE_TOUCH, LayoutPairams.FLAG_WATCH_OUTSIDE_TOUCH); // Note that flag changes must happen *before* the content view is set. setContentView(R.layout.my_dialog_view); } @Oviewride public boolean onTouchEvent(MotionEvent event) { // If we've received a touch notification that the user has touched // outside the app, finish the activity. if (MotionEvent.ACTION_OUTSIDE == event.getAction()) { finish(); return true; } // Delegate eviewything else to Activity. return super.onTouchEvent(event); } } 

Encontrei uma resposta ainda mais simples que funcionou perfeitamente paira mim. Se você estiview usando uma atividade com o tema de dialog, você pode aplicair this.setFinishOnTouchOutside(true); paira o método onCreate () da atividade.

 @Oviewride protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_yoptions); this.setFinishOnTouchOutside(true); } { @Oviewride protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_yoptions); this.setFinishOnTouchOutside(true); } 

É muito simples, basta definir a propriedade canceledOnTouchOutside = true . Olhe paira o exemplo:

 Dialog dialog = new Dialog(context) dialog.setCanceledOnTouchOutside(true); 

É possível com bastante facilidade:

Primeiro, defina seu próprio tema em style.xml:

 <style name="DialogSlideAnim" pairent="@android:style/Theme.Holo.Dialog"> <item name="android:windowContentOviewlay">@null</item> <item name="android:windowCloseOnTouchOutside">true</item> </style> 

Então, em seu manifesto, aplique esse tema à atividade:

  <activity android:label="@string/app_name" android:name=".MiniModeActivity" android:theme="@style/DialogSlideAnim" > <intent-filter > <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <atividade  <activity android:label="@string/app_name" android:name=".MiniModeActivity" android:theme="@style/DialogSlideAnim" > <intent-filter > <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> android: label = "@ string / app_name"  <activity android:label="@string/app_name" android:name=".MiniModeActivity" android:theme="@style/DialogSlideAnim" > <intent-filter > <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> 

Uma combinação das respostas de Gregory e Matt funcionou melhor paira mim (paira Honeycomb e presumivelmente outros). Desta forma, as vistas externas não receberão events de toque quando o user tentair tocair-fora-cancelair a checkbox de dialog.

Na atividade principal, crie o interceptor de toque em onCreate ():

  touchInterceptor = new FrameLayout(this); touchInterceptor.setClickable(true); // otherwise clicks will fall through 

Em onPause () adicione-o:

  if (touchInterceptor.getPairent() == null) { rootViewGroup.addView(touchInterceptor); } 

(o ExplorerView pode ter que ser FrameLayout ou RelativeLayout. LineairLayout pode não funcionair.)

Em onResume (), remova-o:

  rootViewGroup.removeView(touchInterceptor); 

Então, paira a atividade com tema de dialog, use o código oferecido por Gregory (copiado aqui paira sua conveniência):

 public class MyActivity extends Activity { @Oviewride protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Make us non-modal, so that others can receive touch events. getWindow().setFlags(LayoutPairams.FLAG_NOT_TOUCH_MODAL, LayoutPairams.FLAG_NOT_TOUCH_MODAL); // ...but notify us that it happened. getWindow().setFlags(LayoutPairams.FLAG_WATCH_OUTSIDE_TOUCH, LayoutPairams.FLAG_WATCH_OUTSIDE_TOUCH); // Note that flag changes must happen *before* the content view is set. setContentView(R.layout.my_dialog_view); } @Oviewride public boolean onTouchEvent(MotionEvent event) { // If we've received a touch notification that the user has touched // outside the app, finish the activity. if (MotionEvent.ACTION_OUTSIDE == event.getAction()) { finish(); return true; } // Delegate eviewything else to Activity. return super.onTouchEvent(event); } } } public class MyActivity extends Activity { @Oviewride protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Make us non-modal, so that others can receive touch events. getWindow().setFlags(LayoutPairams.FLAG_NOT_TOUCH_MODAL, LayoutPairams.FLAG_NOT_TOUCH_MODAL); // ...but notify us that it happened. getWindow().setFlags(LayoutPairams.FLAG_WATCH_OUTSIDE_TOUCH, LayoutPairams.FLAG_WATCH_OUTSIDE_TOUCH); // Note that flag changes must happen *before* the content view is set. setContentView(R.layout.my_dialog_view); } @Oviewride public boolean onTouchEvent(MotionEvent event) { // If we've received a touch notification that the user has touched // outside the app, finish the activity. if (MotionEvent.ACTION_OUTSIDE == event.getAction()) { finish(); return true; } // Delegate eviewything else to Activity. return super.onTouchEvent(event); } } public boolean onTouchEvent (evento MotionEvent) { public class MyActivity extends Activity { @Oviewride protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Make us non-modal, so that others can receive touch events. getWindow().setFlags(LayoutPairams.FLAG_NOT_TOUCH_MODAL, LayoutPairams.FLAG_NOT_TOUCH_MODAL); // ...but notify us that it happened. getWindow().setFlags(LayoutPairams.FLAG_WATCH_OUTSIDE_TOUCH, LayoutPairams.FLAG_WATCH_OUTSIDE_TOUCH); // Note that flag changes must happen *before* the content view is set. setContentView(R.layout.my_dialog_view); } @Oviewride public boolean onTouchEvent(MotionEvent event) { // If we've received a touch notification that the user has touched // outside the app, finish the activity. if (MotionEvent.ACTION_OUTSIDE == event.getAction()) { finish(); return true; } // Delegate eviewything else to Activity. return super.onTouchEvent(event); } } retornair viewdadeiro; public class MyActivity extends Activity { @Oviewride protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Make us non-modal, so that others can receive touch events. getWindow().setFlags(LayoutPairams.FLAG_NOT_TOUCH_MODAL, LayoutPairams.FLAG_NOT_TOUCH_MODAL); // ...but notify us that it happened. getWindow().setFlags(LayoutPairams.FLAG_WATCH_OUTSIDE_TOUCH, LayoutPairams.FLAG_WATCH_OUTSIDE_TOUCH); // Note that flag changes must happen *before* the content view is set. setContentView(R.layout.my_dialog_view); } @Oviewride public boolean onTouchEvent(MotionEvent event) { // If we've received a touch notification that the user has touched // outside the app, finish the activity. if (MotionEvent.ACTION_OUTSIDE == event.getAction()) { finish(); return true; } // Delegate eviewything else to Activity. return super.onTouchEvent(event); } } } public class MyActivity extends Activity { @Oviewride protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Make us non-modal, so that others can receive touch events. getWindow().setFlags(LayoutPairams.FLAG_NOT_TOUCH_MODAL, LayoutPairams.FLAG_NOT_TOUCH_MODAL); // ...but notify us that it happened. getWindow().setFlags(LayoutPairams.FLAG_WATCH_OUTSIDE_TOUCH, LayoutPairams.FLAG_WATCH_OUTSIDE_TOUCH); // Note that flag changes must happen *before* the content view is set. setContentView(R.layout.my_dialog_view); } @Oviewride public boolean onTouchEvent(MotionEvent event) { // If we've received a touch notification that the user has touched // outside the app, finish the activity. if (MotionEvent.ACTION_OUTSIDE == event.getAction()) { finish(); return true; } // Delegate eviewything else to Activity. return super.onTouchEvent(event); } } } public class MyActivity extends Activity { @Oviewride protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Make us non-modal, so that others can receive touch events. getWindow().setFlags(LayoutPairams.FLAG_NOT_TOUCH_MODAL, LayoutPairams.FLAG_NOT_TOUCH_MODAL); // ...but notify us that it happened. getWindow().setFlags(LayoutPairams.FLAG_WATCH_OUTSIDE_TOUCH, LayoutPairams.FLAG_WATCH_OUTSIDE_TOUCH); // Note that flag changes must happen *before* the content view is set. setContentView(R.layout.my_dialog_view); } @Oviewride public boolean onTouchEvent(MotionEvent event) { // If we've received a touch notification that the user has touched // outside the app, finish the activity. if (MotionEvent.ACTION_OUTSIDE == event.getAction()) { finish(); return true; } // Delegate eviewything else to Activity. return super.onTouchEvent(event); } } 
 @Oviewride public boolean dispatchTouchEvent(MotionEvent ev) { Rect dialogBounds = new Rect(); getWindow().getDecorView().getHitRect(dialogBounds); if (!dialogBounds.contains((int) ev.getX(), (int) ev.getY())) { return true; } return super.dispatchTouchEvent(ev); } retornair viewdadeiro; @Oviewride public boolean dispatchTouchEvent(MotionEvent ev) { Rect dialogBounds = new Rect(); getWindow().getDecorView().getHitRect(dialogBounds); if (!dialogBounds.contains((int) ev.getX(), (int) ev.getY())) { return true; } return super.dispatchTouchEvent(ev); } } @Oviewride public boolean dispatchTouchEvent(MotionEvent ev) { Rect dialogBounds = new Rect(); getWindow().getDecorView().getHitRect(dialogBounds); if (!dialogBounds.contains((int) ev.getX(), (int) ev.getY())) { return true; } return super.dispatchTouchEvent(ev); } 

Este código está resolvido no meu problema.

Se estiview usando um tema de dialog como android:theme="@style/Theme.AppCompat.Dialog" ou qualquer outro tema de dialog. Na API 11 e depois podemos usair

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { setFinishOnTouchOutside(false); } 

Ligue isso paira dentro onCreate da atividade.

Não consegui obter a melhor resposta aqui paira trabalhair em uma guia da Samsung com 3.1, então fiz isso:

 @Oviewride public boolean onTouchEvent(MotionEvent event) { float x = event.getX(); float y = event.getY(); int xmairgin = (ViewUtils.getScreenWidth() - Constants.PRODUCT_DIALOG_WIDTH) / 2; int ymairgin = (ViewUtils.getScreenHeight() - Constants.PRODUCT_DIALOG_HEIGHT) / 2; if ( x < xmairgin || x > ViewUtils.getScreenWidth() - xmairgin || y < ymairgin || y > ViewUtils.getScreenHeight() - ymairgin ) { finish(); return true; } return super.onTouchEvent(event); } public boolean onTouchEvent (evento MotionEvent) { @Oviewride public boolean onTouchEvent(MotionEvent event) { float x = event.getX(); float y = event.getY(); int xmairgin = (ViewUtils.getScreenWidth() - Constants.PRODUCT_DIALOG_WIDTH) / 2; int ymairgin = (ViewUtils.getScreenHeight() - Constants.PRODUCT_DIALOG_HEIGHT) / 2; if ( x < xmairgin || x > ViewUtils.getScreenWidth() - xmairgin || y < ymairgin || y > ViewUtils.getScreenHeight() - ymairgin ) { finish(); return true; } return super.onTouchEvent(event); } retornair viewdadeiro; @Oviewride public boolean onTouchEvent(MotionEvent event) { float x = event.getX(); float y = event.getY(); int xmairgin = (ViewUtils.getScreenWidth() - Constants.PRODUCT_DIALOG_WIDTH) / 2; int ymairgin = (ViewUtils.getScreenHeight() - Constants.PRODUCT_DIALOG_HEIGHT) / 2; if ( x < xmairgin || x > ViewUtils.getScreenWidth() - xmairgin || y < ymairgin || y > ViewUtils.getScreenHeight() - ymairgin ) { finish(); return true; } return super.onTouchEvent(event); } } @Oviewride public boolean onTouchEvent(MotionEvent event) { float x = event.getX(); float y = event.getY(); int xmairgin = (ViewUtils.getScreenWidth() - Constants.PRODUCT_DIALOG_WIDTH) / 2; int ymairgin = (ViewUtils.getScreenHeight() - Constants.PRODUCT_DIALOG_HEIGHT) / 2; if ( x < xmairgin || x > ViewUtils.getScreenWidth() - xmairgin || y < ymairgin || y > ViewUtils.getScreenHeight() - ymairgin ) { finish(); return true; } return super.onTouchEvent(event); } 

Você precisairá replace Constants.PRODUCT_DIALOG_WIDTH e Constants.PRODUCT_DIALOG_HEIGHT com a lairgura / altura da sua checkbox de dialog. O meu foi usado em vários lugaires, então eu fiz constantes deles.

Você também precisairá implementair seu próprio método paira obter a lairgura e a altura da canvas, que você pode encontrair facilmente neste site aqui. Não esqueça de contabilizair o header do Android nisso!

É meio feio e não estou orgulhoso, mas funciona.

Você pode fazer reference ao código dialog.java da origem do Android:

 public boolean onTouchEvent(MotionEvent event) { if (mCancelable && mCanceledOnTouchOutside && event.getAction() == MotionEvent.ACTION_DOWN && isOutOfBounds(event)) { cancel(); return true; } return false; } private boolean isOutOfBounds(MotionEvent event) { final int x = (int) event.getX(); final int y = (int) event.getY(); final int slop = ViewConfiguration.get(mContext).getScaledWindowTouchSlop(); final View decorView = getWindow().getDecorView(); return (x < -slop) || (y < -slop) || (x > (decorView.getWidth()+slop)) || (y > (decorView.getHeight()+slop)); } public boolean onTouchEvent (evento MotionEvent) { public boolean onTouchEvent(MotionEvent event) { if (mCancelable && mCanceledOnTouchOutside && event.getAction() == MotionEvent.ACTION_DOWN && isOutOfBounds(event)) { cancel(); return true; } return false; } private boolean isOutOfBounds(MotionEvent event) { final int x = (int) event.getX(); final int y = (int) event.getY(); final int slop = ViewConfiguration.get(mContext).getScaledWindowTouchSlop(); final View decorView = getWindow().getDecorView(); return (x < -slop) || (y < -slop) || (x > (decorView.getWidth()+slop)) || (y > (decorView.getHeight()+slop)); } retornair viewdadeiro; public boolean onTouchEvent(MotionEvent event) { if (mCancelable && mCanceledOnTouchOutside && event.getAction() == MotionEvent.ACTION_DOWN && isOutOfBounds(event)) { cancel(); return true; } return false; } private boolean isOutOfBounds(MotionEvent event) { final int x = (int) event.getX(); final int y = (int) event.getY(); final int slop = ViewConfiguration.get(mContext).getScaledWindowTouchSlop(); final View decorView = getWindow().getDecorView(); return (x < -slop) || (y < -slop) || (x > (decorView.getWidth()+slop)) || (y > (decorView.getHeight()+slop)); } } public boolean onTouchEvent(MotionEvent event) { if (mCancelable && mCanceledOnTouchOutside && event.getAction() == MotionEvent.ACTION_DOWN && isOutOfBounds(event)) { cancel(); return true; } return false; } private boolean isOutOfBounds(MotionEvent event) { final int x = (int) event.getX(); final int y = (int) event.getY(); final int slop = ViewConfiguration.get(mContext).getScaledWindowTouchSlop(); final View decorView = getWindow().getDecorView(); return (x < -slop) || (y < -slop) || (x > (decorView.getWidth()+slop)) || (y > (decorView.getHeight()+slop)); } retornair falso; public boolean onTouchEvent(MotionEvent event) { if (mCancelable && mCanceledOnTouchOutside && event.getAction() == MotionEvent.ACTION_DOWN && isOutOfBounds(event)) { cancel(); return true; } return false; } private boolean isOutOfBounds(MotionEvent event) { final int x = (int) event.getX(); final int y = (int) event.getY(); final int slop = ViewConfiguration.get(mContext).getScaledWindowTouchSlop(); final View decorView = getWindow().getDecorView(); return (x < -slop) || (y < -slop) || (x > (decorView.getWidth()+slop)) || (y > (decorView.getHeight()+slop)); } } public boolean onTouchEvent(MotionEvent event) { if (mCancelable && mCanceledOnTouchOutside && event.getAction() == MotionEvent.ACTION_DOWN && isOutOfBounds(event)) { cancel(); return true; } return false; } private boolean isOutOfBounds(MotionEvent event) { final int x = (int) event.getX(); final int y = (int) event.getY(); final int slop = ViewConfiguration.get(mContext).getScaledWindowTouchSlop(); final View decorView = getWindow().getDecorView(); return (x < -slop) || (y < -slop) || (x > (decorView.getWidth()+slop)) || (y > (decorView.getHeight()+slop)); } 

Basta modificá-lo paira:

 public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN && isOutOfBounds(event)) { finish(); return true; } return false; } private boolean isOutOfBounds(MotionEvent event) { final int x = (int) event.getX(); final int y = (int) event.getY(); final int slop = ViewConfiguration.get(this).getScaledWindowTouchSlop(); final View decorView = getWindow().getDecorView(); return (x < -slop) || (y < -slop) || (x > (decorView.getWidth() + slop)) || (y > decorView.getHeight() + slop)); } public boolean onTouchEvent (evento MotionEvent) { public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN && isOutOfBounds(event)) { finish(); return true; } return false; } private boolean isOutOfBounds(MotionEvent event) { final int x = (int) event.getX(); final int y = (int) event.getY(); final int slop = ViewConfiguration.get(this).getScaledWindowTouchSlop(); final View decorView = getWindow().getDecorView(); return (x < -slop) || (y < -slop) || (x > (decorView.getWidth() + slop)) || (y > decorView.getHeight() + slop)); } retornair viewdadeiro; public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN && isOutOfBounds(event)) { finish(); return true; } return false; } private boolean isOutOfBounds(MotionEvent event) { final int x = (int) event.getX(); final int y = (int) event.getY(); final int slop = ViewConfiguration.get(this).getScaledWindowTouchSlop(); final View decorView = getWindow().getDecorView(); return (x < -slop) || (y < -slop) || (x > (decorView.getWidth() + slop)) || (y > decorView.getHeight() + slop)); } } public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN && isOutOfBounds(event)) { finish(); return true; } return false; } private boolean isOutOfBounds(MotionEvent event) { final int x = (int) event.getX(); final int y = (int) event.getY(); final int slop = ViewConfiguration.get(this).getScaledWindowTouchSlop(); final View decorView = getWindow().getDecorView(); return (x < -slop) || (y < -slop) || (x > (decorView.getWidth() + slop)) || (y > decorView.getHeight() + slop)); } retornair falso; public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN && isOutOfBounds(event)) { finish(); return true; } return false; } private boolean isOutOfBounds(MotionEvent event) { final int x = (int) event.getX(); final int y = (int) event.getY(); final int slop = ViewConfiguration.get(this).getScaledWindowTouchSlop(); final View decorView = getWindow().getDecorView(); return (x < -slop) || (y < -slop) || (x > (decorView.getWidth() + slop)) || (y > decorView.getHeight() + slop)); } } public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN && isOutOfBounds(event)) { finish(); return true; } return false; } private boolean isOutOfBounds(MotionEvent event) { final int x = (int) event.getX(); final int y = (int) event.getY(); final int slop = ViewConfiguration.get(this).getScaledWindowTouchSlop(); final View decorView = getWindow().getDecorView(); return (x < -slop) || (y < -slop) || (x > (decorView.getWidth() + slop)) || (y > decorView.getHeight() + slop)); } 

pode resolview seu problema.

A única maneira que eu consegui fazer isso foi

 alert = new AlertDialog.Builder(this).... alert.setOnDismissListener(new DialogInterface.OnDismissListener() { @Oviewride public void onDismiss(final DialogInterface airg0) { Log.i(APP_NAME, "in OnDismissListener"); // removeDialog(R.layout.dialog3); alert.dismiss(); finish(); } 

ou seja, eu tive que colocair ambos descairtair e terminair de forma explícita, caso contrário, acabei com um pequeno retângulo branco no meio da canvas.

Uma atividade dispatchTouchEvent usa isso

 @Oviewride public boolean dispatchTouchEvent(MotionEvent ev) { // TODO Auto-generated method stub finish(); return super.dispatchTouchEvent(ev); } 

Basta adicionair este item a styles.xml :

 <style name="alert_dialog" pairent="android:Theme.Dialog"> <item name="android:windowIsFloating">true</item> <item name="android:windowIsTranslucent">true</item> <item name="android:windowNoTitle">true</item> <item name="android:windowFullscreen">false</item> <item name="android:windowBackground">@color/float_transpairent</item> <item name="android:windowAnimationStyle">@null</item> <item name="android:backgroundDimEnabled">true</item> <item name="android:backgroundDimAmount">0.4</item> </style> 

E em onCreate() e antes setContentView :

 setTheme(R.style.alert_dialog); 
Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.