I was wondering if it's possible to somehow tap outside a popup dialog (or an Activity with a dialog theme), and dismiss it by just tapping outside of it?
I made a quick picture to illustrate it:
![](https://www.manongdao.com/static/images/pcload.jpg)
Normally, you have to press the back key to dismiss the dialogs, but on Honeycomb it could be great to have the option of just tapping outside the dialog, due to all the screen estate.
My app is a single activity with Theme.Holo.Dialog. In my case the other answer did not work. It only made the other background apps or the launch screen to receive touch events.
I found that using dispatchTouchEvent works in my case. I think it is also a simpler solution. Here's some sample code on how to use it to detect taps outside the activity with a Dialog theme:
@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);
}
dialog.setCanceledOnTouchOutside(true)
Sets whether this dialog is canceled when touched outside the window's bounds.
There is a TouchInterceptor
method which will called when you touch on out side of popup window
For example
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
is the popup window
And if you want same functionality for Activity you have to follow below steps.
1) Add flag before setContentView()
method called 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()
event in Activity
and write below code
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
Toast.makeText(getApplicationContext(), "Finish", 3000).show();
finish();
return true;
}
return false;
}
The complete copy is here
Activity
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;
}
}
This is 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>
You could use Activity#setFinishOnTouchOutside too, if your dialog is an Activity
. That's gotta be the shortest way for Activity
s ;)
(It's API 11+ though. But API <= 10 is generally screen size normal.)
You may use
dialog.setCancelable(true\false);
For the lastest vesrions of Android;
It will disable outSideTouching event.
Simply I write dialog.setCanceledOnTouchOutside(false); and it work for me, window will not dismiss on outside tap .
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);
Check if you have this line of code or not....
dialog.setCanceledOnTouchOutside(true);
Old question but yet another solution:
Make your foreground activity full-screen. Usenested layouts: The full-screen layout should have transparent background (e.g. @null
or @android:color/transparent
). The inner layout should have a visible background.
Add an OnClickListener
to the invisible outer layout that finish()
es your activity.
Use style of dialog rather than other styles.
For example, Use
public YourCustomDialog(Context context) {
super(context, android.R.style.Theme_Holo_dialog_NoActionBar);
}
When you use other styles like Theme_Translucent_NoTitleBar , the dialog will not be dismissed.
this.setFinishOnTouchOutside(false);
you can use this
LayoutParams lp=dialogp.getWindow().getAttributes();
lp.flags=LayoutParams.FLAG_LAYOUT_NO_LIMITS;
I added this and it works flawlessly on 3.0 up, but should work on all.
Any views within the dialog can set to consume the touch event so that below won't be called.
onCreate(){
getWindow().getDecorView().getRootView().setOnTouchListener(new OnTouchListener(){
@Override
public boolean onTouch(View v, MotionEvent event) {
dialog.dismiss();
return false;
}
});