如何在不显示父活动的情况下将一个全屏对话框片段替换为另一个?

时间:2014-08-26 22:23:39

标签: android android-fragments android-fragmentactivity android-dialogfragment

我有一个使用单个自定义DialogFragment类的Activity。它的外观是数据驱动的,因此从调用到调用看起来都很不一样。

是“全屏”,即

setStyle(DialogFragment.STYLE_NO_FRAME, android.R.style.Theme);

为了响应网络呼叫的结果,我解雇()当前显示的实例(如果有的话)并显示()一个新实例:

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();

这是我的问题:当这个代码块运行时,在现有Fragment消失的点与新的Fragment消失的点之间,我可以简单地看到底层的Activity。我想以某种方式避免这种情况。

我的第一个想法是解散新片段的onResume()方法中的现有片段。也就是说,尽可能地延迟“dismiss()”调用,希望在前一个片段被解除之前新片段已经可见(模糊前一片段)。但这没有效果。

我正在考虑的另一个选项是使片段“可重新配置”,以便我可以“推入”新数据并触发它重绘其所有视图以匹配新数据。在这个解决方案中,我只是重新配置现有的片段(如果有的话),而不是解雇它并显示一个新片段。

我的问题:当解雇一个全屏幕DialogFragment并显示另一个时,有没有更容易和/或更直接的方法来解决基础Activity的临时“偷看”?

4 个答案:

答案 0 :(得分:2)

根据您的活动和全屏片段的外观,我会想到一些选项。

  1. 按照您自己的第一个想法:尝试通过将第一个数据驱动片段发布到根视图的处理程序来安排解雇第一个数据驱动片段。那就是:

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

    这应该确保解雇不会发生,直到 第二个片段变得可见之后。如果您使用onCreateDialog(Bundle savedInstanceState)构建自定义对话框,请务必将视频发布到视图中。

  2. 实例化两个全屏片段并使用show()hide()个事务在它们之间切换(而不是实际的replace()remove() - 和 - { {1}}交易)。在两个片段之间切换时,这些操作应该快得多,因为在执行事务时两者都已经或多或少地完全初始化(换句话说:当切换'时延迟较少)。这将产生一个小的性能影响,但可能可以忽略不计。它是数据驱动片段的理想选择,特别是如果你使用参数包提供数据,但不是很难通过创建一些setter来克服。

  3. 如果两个全屏片段具有相同的背景(即简单的颜色),则可以为活动的背景提供相同的颜色。当片段随后被换出时,视觉结果将是暂时空白的屏幕,但不那么干扰,因为只有内容改变(因为背景将保持不变)。

    现在,如果活动不仅仅是一个容器,而是显示自己的内容,你仍然可以通过引入第三个(全屏,不透明)片段作为额外的层来实现与上面相同的操作,以便在切换时隐藏底层活动。全屏片段。当您这样做时,只需将遮蔽层留在原位,并在返回活动内容时将其关闭。

    如果活动和片段的背景非常丰富且不同,那么最后一个选项可能并不理想。

答案 1 :(得分:0)

可能值得尝试使用FragmentManager执行第一个DialogFragment的删除和在一个事务中添加第二个。我有一个应用程序经常交换覆盖片段,并使用这种方法我从来没有注意到背景片段被揭示。

FragmentManger fm = getSupportFragmentManager();
FragmentTransaction trans = fm.beginTransaction().remove(dialog);
newDialog.show(trans, "insert_tag_here_if_you_want");
trans.commit();

请记住,我通常在容器内使用普通碎片,但同样值得尝试。

答案 2 :(得分:0)

将淡出动画应用于第一个对话框。因此,当第一个对话框被关闭并显示第二个对话框时,第二个对话框将立即出现在第一个对话框的顶部,第一个对话框将在后台缓慢淡出。活动窗口没有出现在此过渡中。

定义alpha动画: 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>

定义窗口动画样式: 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>

由于DialogFragment管理Dialog实例,请将动画应用于对话框实例的窗口。在onStart方法中执行,然后将创建对话框实例。

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

答案 3 :(得分:0)

我在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();
    }