2012-06-14 105 views
12

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

有没有这方面的API?

+1

您正在使用什么样的第三方库以及您正在使用哪种应用程序? –

回答

7

AFAIK - 没有这方面的公共API。

推荐的方法是参考对话框,并检查isShowing(),如有必要请致电dismiss(),但由于您使用的是第三方库,因此这可能不适合您。

您最好打赌的是检查您使用的图书馆的文档。如果这没有帮助,那么你运气不好。

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

+0

有没有办法在onpause中对话ID? – newme

+1

嗯...我看到你的问题....你可以尝试覆盖onCreateDialog方法。您需要维护当前打开的对话框的ID列表,并在您想要退出时关闭它们。如果您使用的库不支持它,请仅使用此方法。如果您意外关闭对话框,则可能会遇到来自第三方库的问题。 (空指针有趣) – Madushan

+0

另外,请注意,此方法和dismissDialog方法已弃用,以支持片段模式。所以我不会说这是最好的方法。而且似乎无法检测到对话关闭时的情况(除非您可以在活动从暂停状态恢复时假设该情况,但请检查以确保在关闭屏幕时也会发生这种情况)。所以你必须在所有已知的对话ID上调用'dismissDialog',这是......好吧......我会说可笑的。 – Madushan

9

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

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

+0

我认为这是很好的解决方案,对于大多数情况下 – Pradeep

12

您可以检查它运行在该活动的活性片段和检查,如果他们中的一个是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; 
    } 
+0

将解散的DialogFragment将从FragmentManager中删除 – twlkyao

+0

我看到流行和移动时刻dismissInternal,但方法getFragments只能从同一个库组中调用。 – twlkyao

1

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

您可以从活动得到根视图,

然后你可以用树遍历算法,看看你是否可以到达任何孩子的看法。如果显示警告框,则不应触及您的任何子视图。

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

+0

从根视图(DecorView)你不能到达对话框,因为对话框在另一个窗口中。我可以做什么是从DecorVie访问不同的'mPrivateFlags',当对话框打开时它从'25201976'变为'29363512'。下一个工作是从这里找到正确的有用的标志https://github.com/android/platform_frameworks_base/blob/master/core/java/android/view/View.java#L1737应该很难 –

+0

嗯,也许'hasWindowFocus'将做到这一点,但我需要更多的测试 –

6

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

我已确认从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; 
} 
+1

现在,我们只需要一种方法来检测何时发生的行为。到目前为止,似乎'OnSystemUiVisibilityChangeListener'返回一个对话框显示在一个Activity上的_first_时间,但是没有后续时间。我会继续挖掘。 – VicVu

相关问题