This may be rather obvious, but I cannot get it.
I am trying to use the suggested way of creating dialogs, by extending DialogFragment. Now, the problem is, I don't know how to invoke it. Documentation states:
DialogFragment newFragment = new FireMissilesDialogFragment();
newFragment.show(getSupportFragmentManager(), "missiles");
but my Activity does not extend FragmentActivity (and due to the design of my application, it cannot extend it), so getSupportFragmentManager() cannot be invoked.
Any workaround for this?
I would like to skip the deprecated way of creating a dialog.
The answer is no.
The FragmentActivity (and it's variants) are the ones that support the FragmentManager and the Fragments.
Common solutions to what you might believe "and due to the design of my application, it cannot extend it"
If you're using a ListActivity, just put a list in your layout.
If you're using a MapActivity, switch to the new map API.
If you're using a TabActivity, that's deprecated, you should use Fragments.
For example you can create a class that extend DialogFragment and invoke it like this:
_dialogFiltre = FragmentDialog.newInstance(R.string.tle_dialog_filter, this);
_dialogFiltre.setValidDialogListener(this);
_dialogFiltre.setCancelable(false);
_dialogFiltre.show(getSupportFragmentManager(), null);
The method new instance :
public static DialogFilter newInstance(int title, Context context) {
FragmentDialog dialog = new FragmentDialog();
Bundle args = new Bundle();
args.putInt("title", title);
dialog.setArguments(args);
dialog._context = context;
return dialog;
}
If you are not in a FragmentActivity i don't see any solution. Why does your application design does not let you use FragmentActivity ?
well you can directly invoke getSupportFragmentManager(); on FragmentActivity but not on Fragment itself. So to invoke getSupportFragmentManager(); what you can do is first get FragmentActivity and on that call getSupportFragmentManager();. So as you're getting FragmentActivity, you can call this function like:
getActivity().getSupportFragmentManager();
here getActivity() returns FragmentActivity associated with your Fragment.
what you have done is
1. First you have created instance of your custom DialogFragment class.
2. you're showing that dialog.
Now as you've already created an instance of custom DialogFragment why not use that to retrieve support for fragment manager. So what you can do is:
DialogFragment newFragment = new FireMissilesDialogFragment();
newFragment.show(newFragment.getActivity().getSupportFragmentManager(), "missiles");
what this will do is you're getting FragmentActivity associated with newFragment and on that FragmentActivity you're calling getSupportFragmentManager();.
Unfortunately I have not tested it but this might work. Try it and let us know.
Related
I have some questions about DialogFragment in Android.
I made CustomDialogFragment that extends DialogFragment and implemented onCreateDialog() function in it.
Now I want to show the Dialog in my Activity.
CustomDialogFragment cdf = new CustomDialogFragment();
cdf.show(getSupportFragmentManager(), "myCustomDialog");
However I can't invoke getSupportFragmentManager() in my Activity.
so my questions are:
Could you please tell me how to solve this problem?
Do I have to use FragmentActivity instead of Activity?
What's the differences between FragmentActivity and Activity?
Use AppCompatActivity instead of Activity to use getSupportFragmentManager() in Your Activity
and use getFragmentManager() or getActivity().getSupportFragmentManager() in fragment
Normally when showing a DialogFragment from an Activity, you do this:
MyDialogFragment myDialogFragment = MyDialogFragment.newInstance(args);
myDialogFragment.show(getSupportFragmentManager(), MY_TAG);
Or if you are in a Fragment, you can do this:
MyDialogFragment myDialogFragment = MyDialogFragment.newInstance(args);
myDialogFragment.show(getActivity().getSupportFragmentManager(), MY_TAG);
Which as far as I can tell is pretty similar to the first since it's finding the Activity and then calling from it.
However, again, assuming we're in a Fragment, would it ever make sense to launch a DialogFragment by doing this instead:
MyDialogFragment myDialogFragment = MyDialogFragment.newInstance(args);
myDialogFragment.show(getChildFragmentManager(), MY_TAG);
Would the calling Fragment be considered the parent of the DialogFragment?
This is due to some issues when using setTargetFragment and then calling getTargetFragment()
see this post with its answer
Failure saving state - target not in fragment manager (setTargetFragment)
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");
Basically Dialogs inactivates the activity at the background. So the DialogFragment does the same with increased complexity. So why should one go for DialogFragment though various subclasses of Dialog are available.
Fragments are used with in your activity, but to present a fragment as dialog (window) using FragmentTransaction and followup with fragment's life-cycle, you need to use DialogFragment. However, you may do use simple Dialog too, but then it has nothing to do with the fragment's life-cycle.
As per google docs:
A DialogFragment can still optionally be used as a normal fragment, if
desired. This is useful if you have a fragment that in some cases
should be shown as a dialog and others embedded in a larger UI.
FragmentDialog is a fragment that can be:
used as fragment, e.g.:
FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
trans.add(R.id.navigation_fragment, mFriendFragment);
trans.commit();
used as dialog, e.g.:
FragmentManager fm = getFragmentManager();
UnsubscribeTabletFragment fragment = new UnsubscribeTabletFragment();
fragment.show(fm, "dialog");
So, if you have a fragment, and the fragment sometimes works as fragment, sometimes works as dialog, then you should use this one.
DialogFragment permits to reuse so part of dialog on your app. Just like fragments do it for your layouts.
Here you have a good article about DialogFragment:
http://android-developers.blogspot.fr/2012/05/using-dialogfragments.html
when u have a dynamic layout in your android app using fragment already, then u need to use it with/in your dialog from an action button click or other click, so this time dialogFragment is more convenient then the normal dialog.