Dialog Fragment and Dismissing Touches to Activity's Views - android

I have an activity and a dialog fragment. What I do is when dialog fragment is being shown and user clicks outside dialog fragment, to show an Alert dialog.
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return object: Dialog(activity!!, theme) {
override fun onTouchEvent(event: MotionEvent): Boolean {
if (MotionEvent.ACTION_OUTSIDE == event.action) {
presentAlertDialog()
return true
}
return super.onTouchEvent(event)
}
}.apply {
setCanceledOnTouchOutside(false)
setCancelable(false)
window?.apply {
setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL)
setFlags(WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH)
}
}
If at the point where user clicked there is no view at the activity, then there is no problem. However, when there is a view (e.g., button ) at the point user clicked, both alert dialog and that view's onClickListener is called. What I want to do is just to show alert dialog and make activity's view to dismiss that touch. Is there a way to do it? Thanks in advance!
Edit: To make clearer, I add a screenshot:
What I want is when user touches outside the dialog fragment (i.e., "Waiting" ) and inside Sign Up button (or any other), I want to show an alert dialog and want Sign Up's onClickListener to dismiss that touch.

Okay i guess i understood a little you have two dialogs and when someone clicks outside of first dialog you want to open another. Here is how you can achieve this.
First set dialog.setCanceledOnTouchOutside(true); then implement cancel() listener
dialog.setOnCancelListener(
new DialogInterface.OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
//Open another dialog here
}
});
It's better to use this rather than handling onTouchEvent by yourselves. Hope this helps let me know if still has any issues. I might write some code if given time. Cheers!

Related

Prevent DialogFragment from dismissing when clicking outside/back button, and show a message asking for confirmation instead

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
}
}

How to get notified in the calling activity when search dialog is closed?

I have an activity with a floating action button that triggers a search dialog. When the search dialog pops up, I am hiding the floating action button by overriding onSearchRequested().
override fun onSearchRequested(): Boolean {
fab.hide()
return super.onSearchRequested()
}
When the dialog is closed, I want to show the fab again. The Android docs: https://developer.android.com/guide/topics/search/search-dialog#LifeCycle say that I should be able to get notified when the dialog is closed by registering an OnDismissListener in the search dialog, but don't say how I can get a handle on the search dialog.
In your activity set a OnDissmissListener on SearchManager: https://developer.android.com/reference/android/app/SearchManager.OnDismissListener
edit:
you can do it like this:
override fun onSearchRequested(): Boolean {
val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
searchManager.setOnDismissListener {
//dismiss code
}
return super.onSearchRequested()
}

Avoid AlertDialog to be dismissed when back button is pressed

I have an AlertDialog that shouldn't close when a certain condition, (a button of it isn't enabled) happens if the back button of the device is pressed.
With the following code, I've managed to partially achieve the desired behavior.
dialog1.setOnCancelListener(new DialogInterface.OnCancelListener()
{
#Override
public void onCancel(DialogInterface dialog)
{
Button button3 = ((AlertDialog)
dialog1).getButton(AlertDialog.BUTTON_NEUTRAL);
if (!button3.isEnabled())
{
dialog1.show();
}
else
{
dialog1.dismiss();
}
}
});
But this code presents 2 problems:
1) There's a small time where dialog1 stops showing to show again, this looks a bit bad.
2) Much more important, one needed button that displays when that button is disabled stops showing, this button doesn't initially show with the dialog, under some circumstance which also triggers that the shown button gets disabled it gets to show. For some reason, it looks like the dialog isn't refreshed to its last state and keeps only the elements that originally had.
Is there anyway so that if the back button is pressed when showing the dialog under the mentioned condition absolutely nothing happens or at the very least to keep the exact same elements it had when dismissed and is later shown again?
Use setCancelable();
Sets whether the dialog is cancelable or not. Default is true.
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setCancelable(false);
this will not let you click outside the dialog to dismiss it, or simply go back closing it
dialog1.setCancelable(false);
Override the onBackPressed() and add check for button disabled:
#Override
public void onBackPressed() {
if (button3.isEnabled()) {
//do something
} else {
super.onBackPressed();
}
}

setCancelable(false) and onBackPressed conflict

I have a problem
I have a non cancelable custom dialog
which mean this custom dialog can only close if presses buton inside the custom dialog, so it won't cancel on backpress or click outside
I tried setCancelable(false) and it works however in my activity I have a onBackPressed and whenever my non cancelable dialog show onBackPressed wont trigger when I click back button because I think they conflict
is their a solution to do this?
EDIT: The purpose is I want the user to click button ok, or skip inside the custom dialog which means this dialog is required before proceeding to next activity
also in onBackPressed since I am using fragment whenever user press back it changes to previous fragment
sorry for lacking of explanation
my code is this
Dialog
dialog_welcome_navigation = DialogUtils.showCustomDialog(context, R.layout.dialog_welcome_navigation);
dialog_welcome_navigation.setCancelable(false); // disable closing dialog with back pressed
dialog_welcome_navigation.setCanceledOnTouchOutside(true);
and the onBackPressed
#Override
public void onBackPressed(){
Log.d("TAG", "--back--");
}
After searching I have found a solution thanks to this SO answer
https://stackoverflow.com/a/25251122/3481654
I add a setOnKeyListener on my dialog
dialog_welcome_navigation.setOnKeyListener(dialogWelcomeNavigationOnKey);
private DialogInterface.OnKeyListener dialogWelcomeNavigationOnKey = new DialogInterface.OnKeyListener() {
#Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
if (keyCode == android.view.KeyEvent.KEYCODE_BACK) {
dialog_welcome_navigation.dismiss();
// move other fragment
return true;
}
return false;
}
};

Display and Hide alternatively a dialog on touching anywhere on screen in android

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

Categories

Resources