我有一个活动可以在运行时显示不同的对话框。我使用 onCreateDialog(int id) 创建每个对话框,并使用 showDialog(int id) 和 DismissDialog(int id) 方法分别显示和关闭每个对话框。
当调用 onPause() 时,我不知道正在显示哪个对话框(如果有)。我想确保当调用 onPause 时,所有对话框都被关闭。是否有推荐的方法来消除所有对话框?我是否必须为每个对话框调用dismissDialog()?
如果您正在使用 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);
}
}
Kotlin 版本:
fun FragmentManager.dismissAllDialogs() {
fragments.forEach { fragment ->
(fragment as? DialogFragment)?.dismissAllowingStateLoss()
fragment.childFragmentManager.dismissAllDialogs()
}
}
取决于我们讨论的对话数量。简短的答案是肯定的,您必须关闭每个对话框。
除了简单地在活动级别声明一些对话框之外,可能还有其他优雅的方法可以做到这一点。一旦声明了所有对话框,您就可以将它们存储在 HashMap 中,然后迭代列表并在 onPause 时关闭每个对话框。
由于您不知道哪些状态是开放的,因此您需要仔细检查并测试或跟踪状态。
但是,如果您的屏幕上确实有这么多对话框,您的 UI/UX 设计可能会遇到一些问题,因为 Android 应该为您提供一个模型,使您可以轻松实现它,而不会出现看起来很糟糕的设计。
随着 Android 最近强调使用 DialogFragment 容器,您不需要对每个
调用解雇由于对话框将有一个片段容器,您可以简单地使用它们的生命周期。考虑这个 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在您的活动中显示它,通常这样调用它:
FragmentManager fm = getSupportFragmentManager();
FragDialog fragDialog = new FragDialog();
fragDialog.show(fm, "my_tag");
请注意,您实际上可以更改 DialogFragment 在 onPause 中执行的操作。当你的activity调用onPause时,这个onPause也会被调用。
使用 this.dismiss() 在 onPause() 中关闭对话框不会完成工作,因为一旦活动恢复,它也会恢复对话框。 (我认为这是因为 savestate 是在 onPause 之前存储的)。
但是,如果您检测到代码中所示的保存实例状态(简历),则可以安全地关闭 onCreate 中的对话框。
在 Kotlin 中你可以让它变得更容易。
如果您想关闭所有 DialogFragment:
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() }
}
我有一个不同的解决方案,这可能很好。您只需将自定义对话框扩展为此
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();
}
}
**
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();
}
}
}
**