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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11026234/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 05:47:02  来源:igfitidea点击:

How to check if the current activity has a dialog in front?

androidandroid-activity

提问by newme

I am using a third-party library and sometimes it pops up a dialog. Before I finish the current activity, I want to check whether there is a dialog popped up in the current context.

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

Is there any API for this?

有没有这方面的 API?

回答by Alécio Carvalho

You can check it running over the active fragments of that activity and checking if one of them is DialogFragment, meaning that there's a active dialog on the screen:

您可以检查它在该活动的活动片段上运行并检查其中一个是否是 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;
    }

回答by Julia Schwarz

I faced a similar problem, and did not want to modify all locations where dialogs were being created and shown. My solution was to look at whether the view I was showing had window focus via the hasWindowFocus()method. This will not work in all situations, but worked in my particular case (this was for an internal recording app used under fairly restricted circumstances).

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

This solution was not thoroughly tested for robustness but I figured I would post in in case it helped somebody.

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

回答by Madushan

AFAIK - there is no public API for this.

AFAIK - 没有为此提供公共 API。

Recommended way is to have a reference to the dialog, and check for isShowing()and call dismiss()if necessary, but since you're using a third party library, this may not be an options for you.

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

Your best bet is to check the documentation for the library you use. If that doesn't help, you're out of luck.

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

Hint: Activity switches to 'paused' state if a dialog pops up. You may be able to 'abuse' this behavior ;)

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

回答by Oliver Jonas

This uses reflection and hidden APIs to get the currently active view roots. If an alert dialog shows this will return an additional view root. But careful as even a toast popup will return an additional view root.

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

I've confirmed compatibility from Android 4.1 to Android 6.0 but of course this may not work in earlier or later Android versions.

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

I've not checked the behavior for multi-window modes.

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

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

回答by Revertron

You can override activity method onWindowFocusChanged(boolean hasFocus)and track the state of your activity.

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

Normally, if some alert dialog is shown above your activity, the activity does not get onPause()and onResume()events. But it loses focus on alert dialog shown and gains it when it dismisses.

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

回答by Pradeep

I am assuming, you are dealing with third party library and you don't have access to dialog object.

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

You can get the root view from the activity,

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

Then you can use tree traversal algorithm to see if you can reach any of the child view. You should not reach any of your child view if alert box is displayed.

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

When alert view is displayed ( check with Ui Automator ), the only element present in UI tree are from DialogBox / DialogActivity. You can use this trick to see if dialog is displayed on the screen. Though it sounds expensive, it could be optimized.

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