I have an Activity that uses a single custom DialogFragment class. Its appearance is data driven, so it can look fairly different from invocation to invocation.
It is "full screen", i.e.
setStyle(DialogFragment.STYLE_NO_FRAME, android.R.style.Theme);
In response to the result of a network call I dismiss() the currently showing instance (if there is one) and show() a new one:
final CustomDialogFragment dialog = (CustomDialogFragment) getSupportFragmentManager().findFragmentByTag(DIALOG_TAG_CUSTOM);
if (dialog != null)
dialog.dismiss();
final CustomDialogFragment newdialog = new CustomDialogFragment();
// configure some stuff on the new fragment that influences its appearance
newdialog.show();
Here is my issue: when this block of code runs, between the point at which the existing Fragment disappears and the new one becomes visible I can briefly see the underlying Activity. I'd like to avoid this somehow.
My first thought was to dismiss the existing fragment inside the onResume() method of the new fragment. That is, to delay the "dismiss()" call as long as possible in hopes that the new fragment would already be visible (obscuring the previous one) before the previous one was dismissed. But this had no effect.
Another option I'm considering is to make the fragment "reconfigurable" so that I can "push in" new data and trigger it to redraw all its views to match the new data. In this solution, I would simply reconfigure the existing fragment (if there is one) instead of dismissing it and showing a new one.
My question: is there an easier and/or more straightforward way to get around this temporary "peek" at the underlying Activity when dismissing one full-screen DialogFragment and showing another?
Depending on what your activity and full-screen fragments look like, a few options come to mind.
Following your own first thought: try scheduling the dismissal of the first data-driven fragment in the second by posting it to the root view's handler. That is:
@Override public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View root = ... // inflate view root.post(new Runnable() { @Override public void run() { // create & commit fragment transaction // to remove first fragment here } }; return root; }
This should ensure that the dismissal doesn't happen until after the second fragment has become visible. If you build a custom dialog using
onCreateDialog(Bundle savedInstanceState)
, make sure you post to the view you inflate there in stead.Instantiate both full-screen fragments and use
show()
andhide()
transactions to switch between them (as opposed to actualreplace()
orremove()
-and-add()
transactions). These operations should be a lot faster to toggle between two fragments, as both will have already been more or less fully initialised upon executing the transaction (in other words: less delay when 'switching'). This will yield a small performance hit, but potentially negligible. It's noy ideal with data-driven fragments, especially if you supply the data using an arguments bundle, but not too hard to overcome by creating some setters.If the two full-screen fragments have an identical background (i.e. a simple colour), then you could give the activity's background the same colour. When the fragments then get swapped out, the visual result will be a momentarily blank screen, but less intrusive, as only the content changes (because the background will stay the same).
Now, if the activity is not merely a container, but displays its own content, you can still achieve the same as above by introducing a third (full-screen, opaque) fragment as an extra layer to obscure the underlying activity while switching between the full-screen fragments. Just leave the obscuring layer in place when you do so, and dismiss it when returning to the activity's content.
If the activity and fragments have a very richly and differently decorated background, then this last option may not be ideal.
It might be worth trying to use the FragmentManager to execute both the removal of the first DialogFragment and the addition of the second in one transaction. I have an application which frequently swaps overlaying fragments out, and using this method I never notice the background fragment being revealed.
FragmentManger fm = getSupportFragmentManager();
FragmentTransaction trans = fm.beginTransaction().remove(dialog);
newDialog.show(trans, "insert_tag_here_if_you_want");
trans.commit();
Keep in mind I usually use this with ordinary fragments within containers, but again it's worth trying.
Apply fade out animation to the first dialog. As a result, when the first dialog is dismissed and second dialog is shown, second dialog will appear immediately on top of first dialog and the first dialog will fade out slowly in the background. There by the activity window does not appear in this transition.
Define an alpha animation : res/anim/dialog_fade_out.xml
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="1.0"
android:toAlpha="0.0"
android:duration="400">
</alpha>
Define window animation style : res/style/custom_dialog_style.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="dialog_fade_out_animation" >
<item name="android:windowExitAnimation">@anim/dialog_fade_out</item>
</style>
</resources>
Since DialogFragment
manages Dialog
instance, apply the animation to the window of dialog instance. Do it in onStart
method, by then dialog instance will be created.
public static class FirstDialogFragment extends DialogFragment {
public void onStart() {
super.onStart();
Dialog d = this.getDialog();
if(d != null)
d.getWindow().setWindowAnimations(R.style.dialog_fade_out_animation);
}
}
I Did Somthing Like this in monoandroid (Xamarin)
public override void OnResume()
{
// Auto size the dialog based on it's contents
Dialog.Window.SetLayout(LinearLayout.LayoutParams.MatchParent, LinearLayout.LayoutParams.WrapContent);
// Make sure there is no background behind our view
//Dialog.Window.SetBackgroundDrawableResource(Resource.Color.transparent_black);
Dialog.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent));
// Disable standard dialog styling/frame/theme: our custom view should create full UI
SetStyle(Android.Support.V4.App.DialogFragment.StyleNoFrame, Android.Resource.Style.Theme);
base.OnResume();
}
来源:https://stackoverflow.com/questions/25516119/how-to-replace-one-full-screen-dialog-fragment-with-another-without-showing-pare