【问题标题】:Android - How to Dismiss All Dialogs in onPauseAndroid - 如何在 onPause 中关闭所有对话框
【发布时间】:2012-03-01 09:11:23
【问题描述】:

我有一个活动可以在运行时显示不同的对话框。我使用 onCreateDialog(int id) 创建每个对话框,并使用 showDialog(int id) 和 dismissDialog(int id) 方法分别显示和关闭每个对话框。

当 onPause() 被调用时,我不知道正在显示哪个对话框(如果有的话)。我想确保在调用 onPause 时,所有对话框都被关闭。有没有推荐的方法来关闭所有对话框?我是否必须为每个对话框调用dismissDialog()?

【问题讨论】:

    标签: android dialog


    【解决方案1】:

    取决于我们谈论的对话数量。简短的回答是肯定的,您必须关闭每个对话框。

    除了简单地在活动级别声明一些对话框之外,可能还有其他优雅的方法可以做到这一点。一旦声明它们,您可以将所有对话框存储在 HashMap 中,然后遍历列表并在暂停时关闭每个对话框。

    由于您不知道哪些是开放的,您需要通过并测试或跟踪状态。

    但是,如果您的屏幕上确实有这么多对话框,则您的 UI/UX 设计可能会出现一些问题,因为 Android 应该为您提供一个模型,该模型可以轻松实现它,而不会出现看似糟糕的设计。

    【讨论】:

    • 另外,为了避免关闭关闭的对话框时出错,您可以在每次关闭对话框时使用 try-catch。这比检查打开的对话框要容易得多。
    【解决方案2】:

    由于 android 最近强调使用 DialogFragment 容器,您将不需要在每个容器上调用dismiss

    由于对话框将有一个片段容器,您可以简单地使用它们的生命周期。考虑这个 DialogFragment:

    public class FragDialog extends DialogFragment{
    
        public ProgressDialog _dialog;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
    
            super.onCreate(savedInstanceState);
    
            if (savedInstanceState != null) {
                //this.dismiss();     <-- The dialogs may be dismissed here
            }
        }
    
        @Override
        public Dialog onCreateDialog(final Bundle savedInstanceState) {
    
            _dialog = new ProgressDialog(getActivity());
            return _dialog;
        }
    
        @Override
        public void onPause() {
            super.onPause();
            // <--------- You may overload onPause
        }
    }
    

    您将使用通常这样调用的片段管理器在您的活动中显示的内容:

    FragmentManager fm = getSupportFragmentManager();
    FragDialog fragDialog = new FragDialog();
    fragDialog.show(fm, "my_tag");
    

    请注意,您实际上可能会更改 DialogFragment 在 onPause 中的作用。当你的活动调用 onPause 时,这个 onPause 也会被调用。

    在 onPause() 中使用 this.dismiss() 关闭对话框不会起作用,因为一旦活动恢复,它也会恢复对话框。 (我认为这是因为保存状态是在 onPause 之前存储的)。

    但是,如果您检测到如代码所示的 savedInstanceState(简历),您可以安全地关闭 onCreate 中的对话框。

    【讨论】:

    • 这是一个简洁的解决方案,并且在 2018 年仍然有效,谢谢!
    【解决方案3】:

    如果您正在使用 DialogFragment 并且想要关闭所有可以使用的内容:

    /**
     * Dismiss all DialogFragments added to given FragmentManager and child fragments
     */
    public static void dismissAllDialogs(FragmentManager manager) {
        List<Fragment> fragments = manager.getFragments();
    
        if (fragments == null)
            return;
    
        for (Fragment fragment : fragments) {
            if (fragment instanceof DialogFragment) {
                DialogFragment dialogFragment = (DialogFragment) fragment;
                dialogFragment.dismissAllowingStateLoss();
            }
    
            FragmentManager childFragmentManager = fragment.getChildFragmentManager();
            if (childFragmentManager != null)
                dismissAllDialogs(childFragmentManager);
        }
    }
    

    【讨论】:

    • 看起来是迄今为止 DialogFragment 最干净的解决方案。您是否在生产应用中使用它?
    • childFragmentManager 为 NonNull,所以不需要检查
    • getFragments() 将在必要时返回一个空列表,因此不需要进行空检查
    【解决方案4】:

    我有一个不同的解决方案,这可能会很好。您只需将自定义对话框扩展至此SiblingDialog,这将使您的Dialog 订阅关闭对话框的广播事件。因此,您可以在任何您想要的地方发送广播事件,所有SiblingDialogs 将被关闭。

    在此示例中,取消和关闭对话框方法已被覆盖,因此 SiblingDialog 本身会在关闭时关闭所有其他同级。

    public class SiblingDialog extends Dialog {
    
        protected LocalBroadcastManager mLocalBroadcastManager;
    
        protected BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                switch (intent.getAction()) {
                    case "CLOSE_ALL_DIALOGS":
                        if (isShowing()) {
                            dismiss();
                        }
                        break;
                    default:
                        break;
                }
            }
        };
        String[] ACTIONS_LIST = {"CLOSE_ALL_DIALOGS"};
    
        public SiblingDialog(Context context) {
            super(context);
        }
    
        public SiblingDialog(Context context, int themeResId) {
            super(context, themeResId);
        }
    
    
        public SiblingDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {
            super(context, cancelable, cancelListener);
        }
    
        private void registerTheBroadCast() {
            mLocalBroadcastManager = LocalBroadcastManager.getInstance(getContext());
            IntentFilter mIntentFilter = new IntentFilter();
            for (String actions : ACTIONS_LIST) {
                mIntentFilter.addAction(actions);
            }
            mLocalBroadcastManager.registerReceiver(mBroadcastReceiver, mIntentFilter);
        }
    
        private void unregisterBroadCast() {
            mLocalBroadcastManager.unregisterReceiver(mBroadcastReceiver);
        }
    
        @Override
        public void show() {
            registerTheBroadCast();
            super.show();
        }
    
        @Override
        public void cancel() {
            unregisterBroadCast();
            mLocalBroadcastManager.sendBroadcast(newIntent("CLOSE_ALL_DIALOGS"));
            super.cancel();
    
        }
    
        @Override
        public void dismiss() {
            unregisterBroadCast();
            mLocalBroadcastManager.sendBroadcast(new Intent("CLOSE_ALL_DIALOGS"));
            super.dismiss();
        }
    }
    

    【讨论】:

      【解决方案5】:

      **

      public static void dismissAllDialogs(FragmentManager manager) {
              List<Fragment> fragments = manager.getFragments();
              if (fragments == null)
                  return;
              for (Fragment fragment : fragments) {
                  if (fragment instanceof DialogFragment) {
                      DialogFragment dialogFragment = (DialogFragment) fragment;
                      dialogFragment.dismiss();
                  }
              }
          }
      

      **

      【讨论】:

        【解决方案6】:

        在 Kotlin 中,你可以让它变得更容易。

        如果您想关闭所有 DialogFragments:

            private fun dismissDialogs() {
                supportFragmentManager.fragments.takeIf { it.isNotEmpty() }
                        ?.map { (it as? DialogFragment)?.dismiss() }
            }
        

        如果您想关闭除一个以外的所有 DialogFragment:

            private fun dismissDialogs(fragment: DialogFragment) {
                supportFragmentManager.fragments.takeIf { it.isNotEmpty() }
                        ?.map { if (it != fragment) (it as? DialogFragment)?.dismiss() }
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-11-20
          • 2011-02-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多