Difference between removeDialog(), dismissDialog() and dismiss() - java

What is different between removeDialog() and dismiss() and dismissDialog()? because I'm able to use them together without any problem.
And is it matter when implementing DialogInterface.OnClickListener or AlertDialog.OnClickListener?
I searched a lot but couldn't find anything useful.
EDIT:
I'm developing for Android 2.3.
Example code:
public final class OptionsPreference extends PreferenceActivity implements DialogInterface.OnClickListener
{
private AlertDialog noInternetDialog = null;
//...
#Override
protected void onPause()
{
if (this.noInternetDialog != null)
{
Log.d(LOG_TAG, "Destroying noInternetDialog...");
this.noInternetDialog.dismiss(); // X?
removeDialog(DIALOG_NOINTERNET); // X?
dismissDialog(DIALOG_NOINTERNET); // X?
this.noInternetDialog = null;
}
super.onPause();
}
#Override
protected final Dialog onCreateDialog(final int id)
{
switch (id)
{
case DIALOG_NOINTERNET:
{
final AlertDialog.Builder _builder = new AlertDialog.Builder(this).setIcon(android.R.drawable.ic_dialog_info).setMessage(R.string.str_nointernet);
_builder.setCancelable(false);
_builder.setPositiveButton(R.string.str_wifisettings, this);
_builder.setNeutralButton(R.string.str_ok, this);
this.noInternetDialog = _builder.create();
if (!isFinishing())
{
this.noInternetDialog.show();
}
return this.noInternetDialog;
}
// ...
}

dismissDialog(int id) : Dismisses the dialog with the specified id. It only hides the dialog but still keeps the internal references by the Activity which contains this dialog so that it can be restored in future.Deprecated in API 13.
removeDialog(int id) : It also dismisses the dialog with the specified id. Means it hides that particular dialog and in addition cleans up all the references by the Activity and hence cannot be restored in future. Deprecated in API 13.
dismiss() : This method operates on a particular dialog because it is a method of Dialog class. It also dismisses the dialog. You have to own a valid dialog in order to dismiss it else you'll get exception.

Related

Returning Data from a Dialog Fragment to the Activity that Called It

Hey fellow stackoverflowers!!!
I'm wondering what the best way to pass a string taken from a Dialog Fragment based on user input on the Dialog into the main activity which called the string?
Here's my specific example but it's really long so if you don't feel like going through it don't worry about everything below.
Here's my source code, I've ommitted the imports n stuff
public class GroupNameFragment extends AppCompatDialogFragment {
private EditText edittGroupName;
public static String GROUP_NAME = "com.example.mashu.walkinggroup.controller - groupName";
// When the views are inflated, get access to them
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
edittGroupName = Objects.requireNonNull(getView()).findViewById(R.id.edittGroupName);
}
#NonNull
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Get reference to fragment's layout
View view = LayoutInflater.from(getActivity())
.inflate(R.layout.group_name_layout, null);
// OK button listener
DialogInterface.OnClickListener listener = (dialog, which) -> {
if (which == DialogInterface.BUTTON_POSITIVE) {
// If OK pressed, create bundle to be accessed in OnDismissListener in MapActivity,
// which contains the groupName user inputted
String groupName = edittGroupName.getText().toString();
Bundle bundle = new Bundle();
bundle.putString(GROUP_NAME, groupName);
setArguments(bundle);
}
};
// Build alert dialog
return new AlertDialog.Builder(getActivity())
.setTitle("Choose your Group Name!")
.setView(view)
.setPositiveButton(android.R.string.ok, listener)
.create();
}
// Extracts groupName from the bundle set up in the onClickListener above
public static String getGroupName(GroupNameFragment dialog) {
Bundle bundle = getArguments();
return bundle.getString(GROUP_NAME);
}
}
What I attempted to do was to this: First, I get access to the EditText that the user will type in their response. Then I set the Dialog Listener for the OK button which creates a bundle using the setArguments function which contains the groupName when the user is done, which will be accessed in the other activity later on by using the static getGroupName function. Here's the function in the main activity which creates the Dialog and sets the onDismissListener
private void createGroupNameDialog() {
// Instantiate Dialog
// Support Fragment Manager for backwards compatibility
FragmentManager manager = getSupportFragmentManager();
GroupNameFragment dialog = new GroupNameFragment();
dialog.show(manager, "GroupNameDialog");
// OnDismissListener callback function to be run whenever dialog dismissed.
dialog.getDialog().setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialogInterface) {
// Update groupName based on what user inputted and update marker name at origin
groupName = GroupNameFragment.getGroupName(dialog);
originMarker.setTitle(groupName);
}
});
}
I think the problem is in groupName = GroupNameFragment.getGroupName(dialog). I feel like theres a better way to get the bundle here, and it seems weird to use the function as static and then pass in specific instance of GroupNameFragment in order to get the bundle (wouldn't that instance be gone by then since it's being used in the "OnDismiss"?). Also, the app crashes the second createGroupNameDialog is called, but it doesn't crash and actually opens the dialog window if I comment out the OnDismissListener, so I'm sure the problems in there somewhere but I don't know why it crashes before the dialog box even opens since OnDismiss happens AFTER the user dismisses the Dialog Box.
Thanks!!!
I accomplished passing variables back using an interface and listeners. I'll show you how I handled it (although I used a DialogFragment, this should still work for AlertDialogs, and in this example I passed an integer, not a string, but it would work for any data type).
public class DialogFragmentOtherMedia extends DialogFragment {
int dialogResult;
//The interface is important!
public interface YesNoListener {
void onYesOtherMedia(int output);
void onNoOtherMedia(int output);
}
//Checking for ClassCastException is nice here.
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (!(activity instanceof YesNoListener)) {
throw new ClassCastException(activity.toString() + " must implement YesNoListener");
}
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
dialogResult = 0;
final String mediaType[] = {getString(R.string.Ringtones),getString(R.string.Music),getString(R.string.Alarms)};
return new AlertDialog.Builder(getActivity())
.setTitle(getString(R.string.Select_Other_Media_Type))
.setSingleChoiceItems(mediaType, dialogResult, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//Log.d("DialogFragmentOtherMedia.onCreateDialog","Item clicked: " + mediaType[which]);
dialogResult = which;
}
})
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//Casting the activity to YesNoListener is very important here!
//You'll register the listener in the activity later, by implementing the interface.
((YesNoListener) getActivity()).onYesOtherMedia(dialogResult);
}
})
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//Same thing for your other callbacks.
((YesNoListener) getActivity()).onNoOtherMedia(dialogResult);
}
})
.create();
}
}
Then you just need to implement it in your activity where you called the dialog from:
public class AlarmDetailsActivity extends Activity
DialogFragmentOtherMedia.YesNoListener {
//All of your activity stuff here...
#Override
public void onYesOtherMedia(int result) {
Log.i("Tag", "onYes Result: " + result);
}
#Override
public void onNoOtherMedia(int result) {
Log.i("Tag", "onNo Result: " + result);
}
}
Sorry about all of the random strings and extra alert dialog. I just wanted to show some actual working code from my app. I tried to add comments next to the important stuff. Hope this helps!

How to properly code the confirm dialogs with Android?

It's supposed to be a very common thing: having dialog boxes to confirm to proceed the flow of the interaction with users. But the best I can come up with with the information I've dug doesn't seem good to me. I primarily extended DialogFragment (following the first searches for examples) and implement the NoticeDialogListener.
I came to believe that this is not the better way because as far as program flow is concerned, it's very cumbersome. Program flow-wise I understand it can be cumbersome anyway as Dialog appears as another thread from the main to begin with, but I suppose there should be a better way to assign different responding method to different dialog. But I haven't been able to find a way except what's following.
Hopefully I've described my question clearly. Thanks in advance for the response.
public class Confirm extends DialogFragment {
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(sQ);
builder
.setPositiveButton(sYes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
mListener.Yes();
}
})
.setNegativeButton(sNo, null);
return builder.create();
}
public interface NoticeDialogListener {
void Yes();
}
private NoticeDialogListener mListener;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mListener = (NoticeDialogListener) activity;
}
}
public class Main extends ActionBarActivity
implements Confirm.NoticeDialogListener {
...
private int iDialogMode;
private final static int DIALOG_ST_0 = 0;
private final static int DIALOG_ST_1 = DIALOG_ST_1 + 1;
private final static int DIALOG_ST_2 = DIALOG_ST_1 + 1;
#Override
public void Yes() {
switch (iDialogMode) {
case DIALOG_ST_0: // follow up HERE0 for what that dialog prompted
break;
case DIALOG_ST_1: // HERE1: feeling not smart
break;
case DIALOG_ST_2: // HERE2: believe there should be a better way
break;
}
}
public ... State_0_doing_something (...) {
...
Confirm diaBox = new Confirm (...);
iDialogMode = DIALOG_ST_0;
diaBox.show(getSupportFragmentManager(), "State_0");
// what's supposed to continue if confirmed will be followed up in HERE0 in Yes()
}
public ... State_1_doing_something_else (...) {
...
Confirm diaBox = new Confirm (...);
iDialogMode = DIALOG_ST_1;
diaBox.show(getSupportFragmentManager(), "State_2");
// what's supposed to continue if confirmed will be followed up in HERE1 in Yes()
}
public ... State_2_doing_yet_something_else (...) {
...
Confirm diaBox = new Confirm (...);
iDialogMode = DIALOG_ST_2;
diaBox.show(getSupportFragmentManager(), "State_3");
// what's supposed to continue if confirmed will be followed up in HERE2 in Yes()
}
}
I am thinking if I can attach a different click listener to each Confirm dialog box created instead of setting the dialog mode/state using global variable/member like that. Am missing function pointers here...
"By the way, how come I couldn't properly post the beginning declaration and ending bracket in the grey box? "
Add 4 blank spaces before that text, or add the ` character at the beggining and end of the code text.
Example:
Fake code that does nothing
"Program flow-wise I understand it can be cumbersome anyway as Dialog appears as another thread from the main to begin with"
This is basically why its not intended for the user to keep on using dialog boxes. The way I saw most programs so far, is that only actions that could severely delay the application or that could possibly charge the user would use dialogs.
Also, note the Activity lifecycle will make you keep its "state" remembered, this can further add to issues with onPause/onResume with your app.
Solved: the only problem is that it's not as nice looking
AlertDialog.Builder builder = new AlertDialog.Builder(Home.theContext);
builder.setMessage(R.string.confirm_delete);
builder.setCancelable(true);
builder.setPositiveButton(R.string.confirm_yes, vCabDelete());
builder.setNegativeButton(Home.theContext.getString(R.string.confirm_no), null);
AlertDialog dialog = builder.create();
dialog.show();
....
private static DialogInterface.OnClickListener vCabDelete() {
return new DialogInterface.OnClickListener() {
public void onClick(DialogInterface di, int id) {
....
}
};
}

OnCancelListener is not called in DialogFragment

I have a simple AlertDialog that displays a list of some items and upon clicking one of them, the clicked item is passed back to the enclosing Activity. I also want to perform some default handling when the user cancels the dialog (using the back button) - more specifically, I want to pass an empty string to the activity in such case.
However, if I put the dialog in a DialogFragment (from the compatibility package), the OnCancelListener is not called when I close the dialog with the back button. What am I doing wrong?
public class SelectItemDialog extends DialogFragment {
public interface Callback {
void onItemSelected(String string);
}
private static final String ARG_ITEMS = "items";
private Callback callback;
public static SelectItemDialog fromItems(Collection<String> items) {
SelectItemDialog fragment = new SelectItemDialog();
fragment.setArguments(newArguments(items));
return fragment;
}
private static Bundle newArguments(Collection<String> items) {
Bundle arguments = new Bundle();
arguments.putStringArray(ARG_ITEMS, items.toArray(new String[items.size()]));
return arguments;
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
callback = (Callback) activity;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final String[] items = getArguments().getStringArray(ARG_ITEMS);
return new AlertDialog.Builder(getActivity())
.setTitle(R.string.dialog_select_email_title)
.setItems(items, new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
callback.onItemSelected(items[which]);
}
})
.setOnCancelListener(new OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
// this code is not executed
callback.onItemSelected("");
throw new RuntimeException("dialog cancelled");
}
})
.create();
}
}
It might have to do with the fact that there is no explicit call to cancel() from your code.
The OnCancelListener documentation says:
This will only be called when the dialog is canceled
Which probably needs an explicit cancel() call.
Either make a positive/negative button with a OnClickListener that calls DialogInterface#cancel() or use a OnDismissListener() with an extra check to see if a list item was clicked.
Also, to listen for a back keypress and cancel the dialog, you can set up an OnKeyListener, like outlined in this SO answer
Also, once you have the Dialog set up, it would also be a good idea to use Dialog#setCanceledOnTouchOutside() in case the the user taps outside the Dialog.
Edit: The below part is the easy way to handle cancel events in a DialogFragment.
Since you are using a DialogFragment, this class has a very handy method, DialogFragment#onCancel() which gets called when the DialogFragment is cancelled. Do your logic in there.
DialogFragments are more complex, with a slightly different lifecycle than normal dialogs. Therefore, first check the documentation if you have a certain Dialog-based approach that you are trying to port to a DialogFragment, some methods may exist that allow your new implementation to function properly!
If you are using DialogFragment and want to listen back button then use this -
this.getDialog().setOnKeyListener(new Dialog.OnKeyListener() {
#Override
public boolean onKey(DialogInterface dialog, int keyCode,
KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (****) {
your logic
}
return true;
}
return false;
}
});
Note: DialogFragment own the Dialog.setOnCancelListener and Dialog.setOnDismissListener callbacks. You must not set them yourself.
To find out about these events, override onCancel(DialogInterface) and onDismiss(DialogInterface).
public class SelectItemDialog extends DialogFragment {
#Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
//your code hear
dialog.cancel();
}
}
And you should remove .setOnCancelListener()
Actually if you want to use DialogFragment, you can never add OnCancelListener or OnDismissListener to it, since the Dialog Fragment owns callbacks to these methods!
You have 3 options here:
1- go with regular dialogs.2- set your dialog fragment to cancellable(false) and add a cancel button to the dialog.3- check #Nikhil Pingle answer.
this is from the documentation of the Dialog Fragment
* <p><em>Note: DialogFragment own the {#link Dialog#setOnCancelListener
* Dialog.setOnCancelListener} and {#link Dialog#setOnDismissListener
* Dialog.setOnDismissListener} callbacks. You must not set them yourself.</em>
* To find out about these events, override {#link #onCancel(DialogInterface)}
* and {#link #onDismiss(DialogInterface)}.</p>
Cancel Listener or Dismiss listener in DialogFragment can achieve by onDismiss
DialogFragment newFragment = new DatePickerFragment();
newFragment.show(getFragmentManager(), "datePicker");
newFragment.onDismiss(new DialogInterface(){
#Override
public void cancel() {
// TODO Auto-generated method stub
}
#Override
public void dismiss() {
// TODO Auto-generated method stub
}
});

How to update AlertDialog content using showDialog(id)

i want to have in my application an alertdialog, that has its message updated everytime it is showed.
This is because the dialog box value depends on some values on the application.
Now i tried to use the showDialog method:
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
showDialog(RESULT_DIALOG);
return false;
}
But once the dialog is created, it doesn't change the message (i know that if the dialog is created, it use the started version).
My onCreateDialog method code is:
public Dialog onCreateDialog(int dialogId) {
AlertDialog dialog;
switch(dialogId) {
case RESULT_DIALOG:
// do the work to define the pause Dialog
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(localTv.getText())
.setCancelable(false)
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
dialog = builder.create();
break;
default:
dialog = null;
}
return dialog;
}
There is a way to update the content of the AlertDialog.
Actually i create a new dialog box every time the onTouch event is called. But i'm not sure that it is the cleanest way to solve that problem.
Any idea?
Thanks :)
You have to use onPrepareDialog method:
#Override
protected void onPrepareDialog ( int id, Dialog dialog ) {
switch ( id ) {
case RESULT_DIALOG:
AlertDialog alertDialog = ( AlertDialog ) dialog;
alertDialog.setMessage( localTv.getText() );
break;
}
super.onPrepareDialog( id, dialog );
}
From http://developer.android.com/guide/topics/ui/dialogs.html :
Before the dialog is displayed, Android also calls the optional
callback method onPrepareDialog(int, Dialog). Define this method if
you want to change any properties of the dialog each time it is
opened. This method is called every time a dialog is opened, whereas
onCreateDialog(int) is only called the very first time a dialog is
opened. If you don't define onPrepareDialog(), then the dialog will
remain the same as it was the previous time it was opened. This method
is also passed the dialog's ID, along with the Dialog object you
created in onCreateDialog().
You can always change the dialog using onPrepareDialog or you can remove the dialog (so it will always pass through onCreateDialog) setting the onDismiss (dialog.setOnDismiss) to remove the dialog id (removeDialog(id)).

how to detect a search button while an alert is shown in an android

Hi stackoverflow friends
I recently faced an issue that how can i disable global search button in android while an alert is shown in the screen.I don't want to disappear the alert box by using search button. I need to user must click the alertbox button and disappears in that way.So I want to disable the search button while alert box is shown. But I can disable the back button using setCancable(false).How can I solve this ?
THanks in advance.
So, Your intention is to provide non-cancelable alert.
Suggesting to set OnDismissListener and just show alert again. It's not very good from visual perspective (alert get closed and opened again).
Below is some obvious example how to achieve such non-cancelable alert (code is inside Acctivity class):
/** reference to our alert */
private AlertDialog alert = null;
/** to indicate if alert dismissed by key */
private boolean alertKeyPressed = false;
#Override
protected void onResume() {
// Say, we need to show alert when activity resumed
if(true/*provide condition to show alert*/) {
showAlert();
}
}
/**
* Show non dismissable alert
*/
private void showAlert() {
if(null == this.alert) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setCancelable(false);
builder.setTitle(R.string.str_alert_title);
builder.setMessage(R.string.str_alert_text);
builder.setIcon(android.R.drawable.ic_dialog_alert);
builder.setNeutralButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
YourActivity.this.alertKeyPressed = true;
dialog.dismiss();
}
});
this.alert = builder.create();
this.alert.setOwnerActivity(this);
this.alert.show();
this.alert.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
// dialog is not allowed to be dismissed, so show it again
YourActivity.this.alert = null;
if(!YourActivity.this.alertKeyPressed) {
showAlert();
}
}
});
}
}
However, I don't think it's the right way to left such alert for the user, sometimes it might be needed for cases like evaluation restriction etc.
Override onSearchRequested in your Activity and have it return false while the dialog is being shown. This should block the request, as per the docs:
You can override this function to force global search, e.g. in
response to a dedicated search key, or to block search entirely (by
simply returning false).
Returns true if search launched, and false if activity blocks it. The
default implementation always returns true.
.setOnKeyListener(new DialogInterface.OnKeyListener()
{
#Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event)
{
//There you catch the key, do whatever you want to do.
//Return true if you handled the key event, so nothing will trigger.
//Return false if you want your activity to handle.
return true;
}
})
Just add the code above to alert dialog builder. Hope this snippet would help. Good luck.

Categories

Resources