如何检查当前活动是否有前面的对话框?

时间:2012-06-14 03:23:01

标签: android android-activity

我正在使用第三方库,有时它会弹出一个对话框。在我完成当前活动之前,我想检查当前上下文中是否弹出了一个对话框。

这有什么API吗?

8 个答案:

答案 0 :(得分:14)

您可以检查它是否在该活动的活动片段上运行,并检查其中一个是否为DialogFragment,这意味着屏幕上有一个活动对话框:

    public static boolean hasOpenedDialogs(FragmentActivity activity) {
        List<Fragment> fragments = activity.getSupportFragmentManager().getFragments();
        if (fragments != null) {
            for (Fragment fragment : fragments) {
                if (fragment instanceof DialogFragment) {
                    return true;
                }
            }
        }

        return false;
    }

答案 1 :(得分:11)

我遇到了类似的问题,并且不想修改创建和显示对话框的所有位置。我的解决方案是通过hasWindowFocus()方法查看我显示的视图是否具有窗口焦点。这不适用于所有情况,但在我的特定情况下工作(这是在相当受限的情况下使用的内部录制应用程序)。

这个解决方案没有经过彻底的稳健性测试,但我想我会发帖,以防它帮助了某人。

答案 2 :(得分:8)

AFAIK - 没有公共API。

推荐的方法是引用对话框,检查isShowing()并在必要时调用dismiss(),但由于您使用的是第三方库,因此这可能不是你。

您最好的选择是查看您使用的库的文档。如果这没有帮助,那你就不走运了。

提示:如果弹出一个对话框,活动会切换到“暂停”状态。您可能会“滥用”此行为;)

答案 3 :(得分:8)

这使用反射和隐藏API来获取当前活动的视图根。如果警报对话框显示这将返回其他视图根。但要小心,即使是一个toast popup也会返回一个额外的视图根。

我已经确认从Android 4.1到Android 6.0的兼容性,但当然这可能不适用于早期或更高版本的Android版本。

我没有检查多窗口模式的行为。

@SuppressWarnings("unchecked")
public static List<ViewParent> getViewRoots() {

    List<ViewParent> viewRoots = new ArrayList<>();

    try {
        Object windowManager;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            windowManager = Class.forName("android.view.WindowManagerGlobal")
                    .getMethod("getInstance").invoke(null);
        } else {
            Field f = Class.forName("android.view.WindowManagerImpl")
                    .getDeclaredField("sWindowManager");
            f.setAccessible(true);
            windowManager = f.get(null);
        }

        Field rootsField = windowManager.getClass().getDeclaredField("mRoots");
        rootsField.setAccessible(true);

        Field stoppedField = Class.forName("android.view.ViewRootImpl")
                .getDeclaredField("mStopped");
        stoppedField.setAccessible(true);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            List<ViewParent> viewParents = (List<ViewParent>) rootsField.get(windowManager);
            // Filter out inactive view roots
            for (ViewParent viewParent : viewParents) {
                boolean stopped = (boolean) stoppedField.get(viewParent);
                if (!stopped) {
                    viewRoots.add(viewParent);
                }
            }
        } else {
            ViewParent[] viewParents = (ViewParent[]) rootsField.get(windowManager);
            // Filter out inactive view roots
            for (ViewParent viewParent : viewParents) {
                boolean stopped = (boolean) stoppedField.get(viewParent);
                if (!stopped) {
                    viewRoots.add(viewParent);
                }
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

    return viewRoots;
}

答案 4 :(得分:1)

我假设您正在处理第三方库,而您无法访问对话框对象。

您可以从活动

获取根视图

然后,您可以使用树遍历算法来查看是否可以访问任何子视图。如果显示警告框,则不应访问任何子视图。

当显示警报视图时(使用Ui Automator检查),UI树中唯一的元素来自DialogBox / DialogActivity。您可以使用此技巧查看屏幕上是否显示对话框。虽然听起来很贵,但可以进行优化。

答案 5 :(得分:1)

您可以覆盖活动方法onWindowFocusChanged(boolean hasFocus)并跟踪活动的状态。

通常情况下,如果您的活动上方显示了一些警告对话框,则该活动不会获得onPause()onResume()个事件。但它失去了对所显示的警报对话框的关注,并在它解散时获得它。

答案 6 :(得分:0)

如果您仅使用Kotlin:

supportFragmentManager.fragments.any { it is DialogFragment }

答案 7 :(得分:0)

对于任何阅读此书并想知道如何在片段或活动上方检测到Dialog的人来说,我的问题是我想在基本片段内部检测是否在自己的上方显示了Dialog分段。该对话框本身是根据我的活动显示的,我不想到达那里,所以我想出的解决方案(感谢与此类问题有关的所有答案)是获得view(或您可以获取我的片段的view.rootView),并检查其子集中是否有焦点。如果它的所有子项都没有焦点,则意味着在我的片段上方显示了某些内容(希望是Dialog)。

// Code inside my base fragment:
val dialogIsDisplayed = (view as ViewGroup).children.any { it.hasWindowFocus() }