I have a dialog that I want to be dismissed when I click outside it. However, I don't want it to receive key events, because it's a volume dialog, and I want the activity to be able to receive the key volume up and down events. So I setted FLAG_NOT_FOCUSABLE, as you see below:
AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.MyDialogTheme);
AlertDialog alert = builder.create();
Window window = alert.getWindow();
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
alert.setView(view);
the problem is that, with this flag, I also can't make the dialog dismiss when a touch outside it happens.
All the solutions on How to dismiss the dialog with click on outside of the dialog? like dialog.setCanceledOnTouchOutside(true); wont work in this case.
1 - Set the flag-FLAG_NOT_TOUCH_MODALfor your dialog's window attribute
Window window = this.getWindow();
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
2 - Add another flag to windows properties,,FLAG_WATCH_OUTSIDE_TOUCH- this one is for dialog to receive touch event outside its visible region.
3 - Override onTouchEvent()of dialog and check for action type. if the action type is 'MotionEvent.ACTION_OUTSIDE' means, user is interacting outside the dialog region. So in this case, you can dimiss your dialog or decide what you wanted to perform. view plainprint?
public boolean onTouchEvent(MotionEvent event)
{
if(event.getAction() == MotionEvent.ACTION_OUTSIDE){
System.out.println("TOuch outside the dialog ******************** ");
this.dismiss();
}
return false;
}
Related
I have a DialogFragment that allows the user to input long messages. By default, if the user clicks outside the DialogFragment or back button, the dialog is dismissed and the user inputs will be lost.
If I use "this.isCancelable = false", it entirely prevents the back button/outside click from firing, which I do not want.
Instead, I want to have a popup message to appear with "Are you sure you want to discard changes", and dismiss DialogFragment only if the user clicks yes then. How should I do this?
Edit: also tried to solve this with flags but still having issues.
Add to DialogFragment's "override fun OnResume()"
//FLAG_WATCH_OUTSIDE_TOUCH requires FLAG_NOT_TOUCH_MODAL to work
dialog?.window?.addFlags(
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
)
dialog?.window?.addFlags(
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
)
dialog?.window?.decorView?.setOnTouchListener { v, event ->
if (event.action == MotionEvent.ACTION_OUTSIDE) {
//action to show a message
}
true
}
Problem with this approach is due to FLAG_NOT_TOUCH_MODAL, I can now click items behind the dialog, which messes up the navigation controller and breaks the app. Is it possible to monitor MotionEvent.ACTION_OUTSIDE, but prevents any actual clicks outside the dialog?
You can set setCanceledOnTouchOutside boolean to true and use the below method for events.
dialog.setOnCancelListener(
new DialogInterface.OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
//When you touch outside of dialog bounds,
//the dialog gets canceled and this method executes.
}
}
);
Show toast or dialog which you want for user confirmation in this onCancel method.
Hope this helps!
OR
1 Set the flag-FLAG_NOT_TOUCH_MODAL for your dialog's window attribute
Window window = this.getWindow();
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
2 Add another flag to windows properties, FLAG_WATCH_OUTSIDE_TOUCH - this one is for dialog to receive touch event outside its visible region.
3 Override onTouchEvent() of dialog and check for action type. if the action type is 'MotionEvent.ACTION_OUTSIDE' means, the user is interacting outside the dialog region. So in this case, you can open another dialog for user confirmation.
public boolean onTouchEvent(MotionEvent event)
{
if(event.getAction() == MotionEvent.ACTION_OUTSIDE){
System.out.println("TOuch outside the dialog");
this.dismiss();
}
return false;
}
Found the solution, credit to #Unknownweirdo, How to dismiss the dialog with click on outside of the dialog?
Kotlin code:
override fun onResume() {
super.onResume()
dialog?.window?.addFlags(
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
)
dialog?.window?.decorView?.setOnTouchListener { v, event ->
if (event.action == MotionEvent.ACTION_DOWN) {
val dialogBounds = Rect()
v.getHitRect(dialogBounds)
if (!dialogBounds.contains(event.x.toInt(), event.y.toInt())) {
// You have clicked the grey area
logicToConfirmDiscardingChange()
false // stop activity closing
}
}
true
}
}
I want to know how to close a pop_up window once the user clicks outside it, I had a look at PopupWindow - Dismiss when clicked outside but without any luck, and I tried that code:
pw.setBackgroundDrawable(null);
pw.setOutsideTouchable(true);
pw.setTouchInterceptor(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event)
{
if(event.getAction() == MotionEvent.ACTION_OUTSIDE)
{
pw.dismiss();
return true;
}
return false;
}
});
Try this out.Hope it works :)
solution 1:
popupWindow.setFocusable(true);
popupWindow.update();
If this dont work.Then you can try this out.
solution 2:
You can use dialog.setCanceledOnTouchOutside(true); which will close the dialog if you touch outside of the dialog.
Something like,
Dialog dialog = new Dialog(context)
dialog.setCanceledOnTouchOutside(true);
Or if your Dialog in non-model then,
1 - Set the flag-FLAG_NOT_TOUCH_MODAL for your dialog's window attribute
Window window = this.getWindow();
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
2 - Add another flag to windows properties,, FLAG_WATCH_OUTSIDE_TOUCH - this one is for dialog to receive touch event outside its visible region.
3 - Override onTouchEvent() of dialog and check for action type. if the action type is 'MotionEvent.ACTION_OUTSIDE' means, user is interacting outside the dialog region. So in this case, you can dimiss your dialog or decide what you wanted to perform. view plainprint?
public boolean onTouchEvent(MotionEvent event)
{
if(event.getAction() == MotionEvent.ACTION_OUTSIDE){
System.out.println("TOuch outside the dialog ******************** ");
this.dismiss();
}
return false;
}
Ok so fixed in the end.
First made the main layout which the popup sits on a relative layout. Then placed a full screen blank layout on top which I made invisible and transparent.
Then show when the popup is shown, set the full screen panel visible with setVisibility(View.VISIBLE); and hide when popup is hidden with setVisibility(View.GONE);
Also need to return true from an on touch listener for the layout with (To stop touch events passing back to the main layout):
blocker.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
And give the popup window the properties:
setTouchable(true);
setOutsideTouchable(false);
Cheers
you should'nt set the BackgroundDrawable to null, because that kills the OnTouchListener ;
you should replace pw.setBackgroundDrawable(null); by pw.setBackgroundDrawable(new BitmapDrawable())
Better use a dialog Fragment for the same. It is made for the popup functionality and closes by default on pressing outside the dialog Fragment or using the hard back button.
I have to restrict alert dialog getting closed on clicking on search button of the device, how to achieve it in android?
Scenario:
My app has one activity with list of data, user can select the data in the list and perform edit, delete etc... on it, if user tries to press edit,delete button of App without selecting an item from list then it pops up alert dialog with message saying "Please select an item" with Ok button.So when the alert dialog pops up if user presses Search button of the device , alert dialog gets closed, I just want to restrict closing of alert dialog.
Please help me to resolve this.
Try this :
dialog.setCanceledOnTouchOutside(false);
It will restrict close only out-side click of alert dialog.
Set key Listener to your AlertDialog Builder and track the KeyEvent.KEYCODE_SEARCH. Or Override onKeyDown() in your Activity..
For AlertDialog Builder Something like,
.setOnKeyListener(new DialogInterface.OnKeyListener() {
#Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_SEARCH && event.getRepeatCount() == 0) {
return true;
}
return false;
}
})
Use Dialog.setCancelable(false); before showing the dialog
Else you can handle the button press like how others have explained here
I am developing a small app wherein a dialog must popup when the user touches anywhere on the screen and if the dialog is already being displayed then on clicking anywhere outside the dialog box it must disappear. Someone plz give suggestions as to how to go about doing this.
This is possibly duplicate of link
if you want to hide dialog box after touch event then
Dialog dialog = new Dialog(context);
dialog.setCanceledOnTouchOutside(true);
and by overriding the onTouch listener as
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
dialog.dismiss();
}
return false;
}
I have a dialog:
final Dialog dialog = new Dialog(context);
dialog.setContentView(R.layout.location_dialog);
dialog.setTitle("My dialog");
dialog.setMessage("My dialog's content");
dialog.setCancelable(true);
dialog.setCanceledOnTouchOutside(true);
dialog.show();
I want to be able to detect touches over and outside the dialog box's lines.
I can easily detect any touches outside the dialog box area with the build-in method
dialog.setCanceledOnTouchOutside(true);
But how can I detect the touches inside this area?
Create an extension of Dialog and override necessary method: dispatchTouchEvent or onTouchEvent (From docs: This is most useful to process touch events that happen outside of your window bounds, where there is no view to receive it.)
Updated:
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Rect dialogBounds = new Rect();
getWindow().getDecorView().getHitRect(dialogBounds);
if (dialogBounds.contains((int) ev.getX(), (int) ev.getY())) {
Log.d("test", "inside");
} else {
Log.d("test", "outside");
}
return super.dispatchTouchEvent(ev);
}