我正在使用第三方库,有时它会弹出一个对话框。在我完成当前活动之前,我想检查当前上下文中是否弹出了一个对话框。
这有什么API吗?
答案 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() }