I'm rewriting an existing app for Honeycomb and I've run into a problem. In the existing app, we create the an AlertDialog with default title and message values, then replace them later if needed. To replace them, we use setTitle() and setMessage():
AlertDialog dialog = getDialog();
if (some condition) {
dialog.setTitle(R.string.error1);
dialog.setMessage(getResources().getString(R.string.error1_msg));
}
else {
dialog.setTitle(R.string.error2);
dialog.setMessage(getResources().getString(R.string.error2_msg));
}
However, now that we are using DialogFragment, there is no method for setTitle() or setMessage(), so we can't change it after it has been created. Is there a workaround for this case, or are we out of luck?
You have to extend the DialogFragment to provide content. See the documentation for examples and other options.
Related
Is there any way to invoke method in MyDialog extends Dialog from fragment that it creates? So I could use Context but don't know how.
The example is dialog that pick Open camera, gallery ect
Yes, you can use an Interface in your Dialog for that purpose. You'll find an example at http://developer.android.com/guide/topics/ui/dialogs.html (you'll find the example under "Passing Events Back to the Dialog's Host").
pretty easy, whenever opening the dialog use a TAG to mark it:
DialogFragment.show(FragmentManager fm, String tag);
dialogFragment.show(getFragmentManager(), "MY_DIALOG");
then to retrieve it you call it:
MyDiagFrag diagFrag = (MyDiagFrag)getFragmentManager()
.findFragmentByTag("MY_DIALOG")
I have a DialogFragment that I launch when a user taps a menu item on the ActionBar. Everything about the Dialog functions properly - it launches just fine and it does everything I've set it up to do. Unfortunately, as soon as I rotate my device, the DialogFragment disappears.
This seemed to be a common problem back in 2012 - I've scoured StackOverflow and tried all of the common fixes that have been posted in the last couple of years. This SO post in particular summarizes all of the potential fixes that have been proposed:
Set up the DialogFragment to use the newInstance() paradigm
Add setRetainInstance(true) to the DialogFragment's onCreate()
Add a workaround to onDestroyView() to address a potential bug in the support library
Despite implementing everything above, the DialogFragment refuses to stick around after device rotation.
Here's how I launch the DialogFragment from the Activity:
DialogKanjiLookup dialog = DialogKanjiLookup.newInstance(gSearchView.getQuery());
dialog.show(getSupportFragmentManager(), "dialogKanjiLookup");
Here is the DialogFragment's newInstance():
public DialogKanjiLookup() {}
public static DialogKanjiLookup newInstance(CharSequence searchTerm)
{
DialogKanjiLookup dialog = new DialogKanjiLookup();
Bundle args = new Bundle();
args.putCharSequence(BUNDLE_SEARCH, searchTerm);
dialog.setArguments(args);
return dialog;
}
Here's the dialog's `onCreateDialog():
#Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
// Specify a layout for the dialog
LayoutInflater inflater = getActivity().getLayoutInflater();
View layout = inflater.inflate(R.layout.dialog_kanjilookup, null);
// SNIP
// ...Handle savedInstanceState, set up various Listeners and adapters...
// SNIP
// Create the actual dialog
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Customize the dialog
builder.setTitle(R.string.dialog_kanji_lookup_title);
builder.setIcon(R.drawable.kanji_lookup);
builder.setPositiveButton(R.string.menu_search, btnSearchListener);
builder.setNegativeButton(R.string.cancel, null);
builder.setView(layout);
// Force the dialog to take up as much space as it can
Dialog dialog = builder.create();
dialog.show();
dialog.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);
// Display the dialog
return dialog;
}
There's only one instance of DialogFragment.dismiss() called from within the fragment but that's only triggered when the user taps one of the dialog's buttons, so I've ruled that out. Why does my DialogFragment still disappear after rotation? I'm all but pulling my hair out over this, it worked fine until sometime after I implemented a Navigation Drawer. Could that be a part of the problem?
EDIT: False alarm, I discovered that my answer wasn't the solution! The problem reappeared after I finished moving all of my Fragments and Activities away from using the Support Libraries.
I did discover that this problem only exists in Activities in which the content fragment has not been declared statically in the Activity's layout. That is, if I have a <FrameLayout> defined in XML and use fragmentManager.beginTransaction().replace(R.id.content_frame, frag, tag).commit(); to load a fragment, any DialogFragments launched in that activity fail to reload when the device has been rotated.
Here's a screen recording that demonstrates the issue:
https://www.youtube.com/watch?v=psK0pzMn6oc
After some experimentation I discovered a solution. The Activity that launches the dialog needs to extend android.support.v4.app.FragmentActivity, and the DialogFragment needs to extend android.support.v4.app.DialogFragment.
Then, getSupportFragmentManager() must be called when launching the DialogFragment:
CustomDialog dialog = CustomDialog.newInstance();
dialog.show(getSupportFragmentManager(), "customDialog");
This should retain the dialog during rotation. There was no need to use setRetainInstance(true) in the dialog itself.
Mind you, this only works in instances in which an FragmentActivity calls a DialogFragment. I'm still trying to suss out a way to preserve a dialog that gets called via a Fragment instead.
The situation is this. I have a subclass of activity at the end of a long inheritance chain that I cannot change. so I cannot make my activity extend FragmentActivity. I wish to display dialogs without leaking them when rotations and such happen.
Google suggested mainly the (now deprecated) dismissDialog(int). The deprecation messege suggests using fragments for dialogs. which makes sense. But as I said I cannot extend FragmentActivity and so cannot get the fragmet manager to launch my dialog fragment. I'm also targeting min sdk 9 and would like to avoid using deprecated methods.
One solution I thought of was calling start for result on a dummy FragmentActivity to show my dialogFragment. but that seems to defeat the porpuse of dialogs entirely.
Is there any hope at all ? Can I somehow launch a dialog fragment from a non fragment activity ? Can I show and dismiss dialogs in a non deprecated way ? Any other alternative I missed ?
Well I would advice you to fix everything and extend FragmentActivity. But Anyway since can not be done without a FragmentActivity, here is a work-around
Create a FragmentActivity that is invisible (pretty easy with a translucent theme)
Start this activity to handle dialogs inside it.
Finish it when dialogs are dismissed or so.
I've finally procedded to manually handle my dialogs. which means:
Dialog currentdialog; // holds the current open dialog
#Override
protected void onSaveInstanceState (Bundle outState){
super.onSaveInstanceState(outState);
...
if(currentdialog!=null){
currentdialog.dismiss();
}
}
public void makeDialog(){
AlertDialog.Builder alert = new AlertDialog.Builder(this);
// set some of the dialog fields
currentdialog = alert.create();
currentdialog.show();
}
It will work:
CustomFieldsDialog customDialog = new
CustomFieldsDialog();
customDialog.show(getActivity().getSupportFragmentManager(),
"CustomFieldsDialog");
I've searched everywhere and I can't find a solution to this problem.
Basically I have a login screen and I'm trying to get a progress spinner to show up while it's logging in to the server (via a thread), and then dismiss it after the login is successful. It has to work while changing orientations.
I am using DialogFragment with the Android compatibility package to make a progress bar (can't find any documentation on it, only for basic\alert dialog) because showDialog() is deprecated now. Right now I just show a custom message box as a login spinner.
In Summary:
How can I set up a Progress spinner with DialogFragment.
How can I dismiss it in another thread after orientation changes.
For showing a progress spinner, just override DialogFragment.onCreateDialog() in your dialog fragment like this (no need for overriding onCreateView()):
#Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
final ProgressDialog dialog = new ProgressDialog(getActivity());
//
dialog.setTitle(R.string.login_title);
dialog.setMessage(getString(R.string.login_message));
dialog.setIndeterminate(true);
dialog.setCancelable(false);
// etc...
return dialog;
}
As for dismissing that dialog fragment from somewhere else, you'll need to get a hold of FragmentManager (from inside your next FragmentActivity or Fragment) and call popBackStack() on it (if you don't do any other fragment transaction in the meantime).
If there's more steps/fragment transactions between your progress dialog fragment and the next activity, you'll probably need one of the other popBackStack(...) methods that take an ID or tag to pop everything up to your progress dialog fragment off the stack.
I know this is old question but I want to share much better solution for this
According to Android Development Protip:
"Stop using ProgressDialog,Inline indicators are your friend"
As Roman Nurik states:
This one's quick. Stop using ProgressDialog and other modal loading
indicators. They're extremely interruptive and annoying, especially
when:
You see one every time you switch tabs.
You can't Back out of them.
They say "Please wait." No thanks, I'd rather just uninstall.
Either show loading indicators inline with your content (e.g.
http://developer.android.com/training/animation/crossfade.html) or better yet, load small amounts of data in the
background so that you minimize the need to even show a loading
indicator.
More about progress & activity in the design guidelines.
I have a class that extends android.app.Dialog, the layout is done in an xml file, and the setup (button listeners, etc) is done on the onCreate method. My problem is that whenever the dialog is displayed, then dismissed, and displayed again, the Editable TextViews are still populated with the information that was displayed previously. What is the common way to clear these text fields? Remember - this is a separate class that extends Dialog - so there is no 'onDialogCreate' like Activity has.
Or, perhaps I am extending the wrong class? There is just a lot of processing being done, and do not want to have all the code in the main Activity. I would like it to be in a separate Class. I tried to extend AlertDialog, but it does not create the border like Dialog does. Any help would be great.
The dialog is shown via the Activity:
protected Dialog onCreateDialog(int id) {
switch(id){
case DIALOG_NEW_SAFE:
return(new NewSafeDialog(this));
default:
return(null);
}
}
onCreateDialog(..) caches the dialog which means the same instance is reused.
3 ways to fix the undesired behavior off my head:
Override onPrepareDialog(..), use findViewById(..) to get whatever you want to clear, clear it.
Don't rely on managed dialogs at all, do new NewSafeDialog(this).show() each time you want to show the dialog.
Add onCancelListener(..), onDismissListener(..) inside your custom dialog that would call a method to clear itself.
The good way to create a dialog is by using showDialog() as you did so don't change it.
The good and easy way to force deletion of a dialog in order to make your creation code recalled again is:
void removeDialog (int id)
So if you simply do the following, it's gonna work ;)
removeDialog(DIALOG_NEW_SAFE);
showDialog(DIALOG_NEW_SAFE);
Try clearing the text in the constructor of the NewSafeDialog i.e. your dialog class.