我正在使用第三方库,有时它会弹出一个对话框。在完成当前活动之前,我想检查当前上下文中是否弹出对话框。
有没有这方面的API?
您可以检查它是否在该活动的活动片段上运行,并检查其中一个是否是 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;
}
我遇到了类似的问题,并且不想修改所有创建和显示对话框的位置。hasWindowFocus()
我的解决方案是通过该方法查看我显示的视图是否具有窗口焦点。这不适用于所有情况,但适用于我的特定情况(这是用于在相当有限的情况下使用的内部录音应用程序)。
这个解决方案没有经过彻底的健壮性测试,但我想我会发布以防它帮助某人。
这使用反射和隐藏 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;
}
AFAIK - 没有为此的公共 API。
推荐的方法是引用对话框,并在必要时检查isShowing()
并调用dismiss()
,但由于您使用的是第三方库,这可能不适合您。
最好的办法是检查您使用的库的文档。如果这没有帮助,那你就不走运了。
提示:如果弹出对话框,活动将切换到“暂停”状态。您也许可以“滥用”这种行为;)
您可以覆盖活动方法onWindowFocusChanged(boolean hasFocus)
并跟踪活动的状态。
通常,如果您的活动上方显示一些警报对话框,则活动不会获取onPause()
和onResume()
事件。但它失去了对显示的警报对话框的关注,并在它关闭时获得它。
对于阅读本文并想知道如何检测Dialog
上述片段或活动的任何人,我的问题是在我的基本片段中,我想检测是否Dialog
在我的片段顶部显示一个。对话框本身是从我的活动中显示的,我不想在那里找到它,所以我想出的解决方案(感谢与此类问题相关的所有答案)是获得view
(或者你可以得到view.rootView
)我的片段并检查它的任何孩子是否有焦点。如果没有一个孩子没有焦点,则意味着Dialog
在我的片段上方显示了一些东西(希望是 a )。
// Code inside my base fragment:
val dialogIsDisplayed = (view as ViewGroup).children.any { it.hasWindowFocus() }
我假设,您正在处理第三方库并且您无权访问对话框对象。
您可以从活动中获取根视图,
然后您可以使用树遍历算法来查看是否可以到达任何子视图。如果显示警告框,您不应访问任何子视图。
当显示警报视图时(使用 Ui Automator 检查),UI 树中存在的唯一元素来自 DialogBox / DialogActivity。您可以使用此技巧查看屏幕上是否显示对话框。虽然听起来很昂贵,但它可以优化。
如果您只使用 Kotlin:
supportFragmentManager.fragments.any { it is DialogFragment }