2012-06-14 165 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

相關問題