23

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

有没有这方面的API?

4

8 回答 8

18

您可以检查它是否在该活动的活动片段上运行,并检查其中一个是否是 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;
    }
于 2015-06-30T10:37:29.690 回答
16

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

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

于 2014-12-01T23:30:59.240 回答
11

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

我已经确认了从 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;
}
于 2016-05-30T22:46:10.707 回答
10

AFAIK - 没有为此的公共 API。

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

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

提示:如果弹出对话框,活动将切换到“暂停”状态。您也许可以“滥用”这种行为;)

于 2012-06-14T03:48:30.127 回答
8

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

通常,如果您的活动上方显示一些警报对话框,则活动不会获取onPause()onResume()事件。但它失去了对显示的警报对话框的关注,并在它关闭时获得它。

于 2018-04-28T11:54:46.393 回答
2

对于阅读本文并想知道如何检测Dialog上述片段或活动的任何人,我的问题是在我的基本片段中,我想检测是否Dialog在我的片段顶部显示一个。对话框本身是从我的活动中显示的,我不想在那里找到它,所以我想出的解决方案(感谢与此类问题相关的所有答案)是获得view(或者你可以得到view.rootView)我的片段并检查它的任何孩子是否有焦点。如果没有一个孩子没有焦点,则意味着Dialog在我的片段上方显示了一些东西(希望是 a )。

// Code inside my base fragment:
val dialogIsDisplayed = (view as ViewGroup).children.any { it.hasWindowFocus() }
于 2020-11-25T13:22:47.267 回答
1

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

您可以从活动中获取根视图,

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

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

于 2016-02-08T09:44:22.627 回答
1

如果您只使用 Kotlin:

supportFragmentManager.fragments.any { it is DialogFragment }
于 2020-08-27T21:19:17.933 回答