サードパーティのライブラリを使用していますが、ダイアログが表示されることがあります。現在のアクティビティを終了する前に、現在のコンテキストでダイアログがポップアップしているかどうかを確認したいと思います。
このための API はありますか?
サードパーティのライブラリを使用していますが、ダイアログが表示されることがあります。現在のアクティビティを終了する前に、現在のコンテキストでダイアログがポップアップしているかどうかを確認したいと思います。
このための API はありますか?
そのアクティビティのアクティブなフラグメントを実行し、そのうちの 1 つが 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 を使用して、現在アクティブなビューのルートを取得します。警告ダイアログが表示された場合、追加のビュー ルートが返されます。ただし、トースト ポップアップでも追加のビュー ルートが返されるので注意してください。
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;
}
私の知る限り-これには公開APIはありません。
推奨される方法は、ダイアログへの参照を持ち、必要に応じて確認しisShowing()
て呼び出すdismiss()
ことですが、サードパーティのライブラリを使用しているため、これはオプションではない場合があります。
最善の策は、使用するライブラリのドキュメントを確認することです。それが役に立たない場合は、運が悪いです。
ヒント: ダイアログがポップアップすると、アクティビティは「一時停止」状態に切り替わります。この振る舞いを「悪用」できるかもしれません ;)
これを読んで、Dialog
上記のフラグメントまたはアクティビティを検出する方法を知りたい人にとって、私の問題は、フラグメントの上に表示されているかどうかを検出したいベースフラグメント内でしたDialog
。ダイアログ自体は私のアクティビティから表示されたもので、そこに到達したくなかったので、思いついた解決策 (この種の質問に関連するすべての回答のおかげで) を取得することでしたview
(または取得できますview.rootView
) の私のフラグメントを作成し、その子のいずれかにフォーカスがあるかどうかを確認します。その子のいずれにもフォーカスがない場合Dialog
、フラグメントの上に何か (できれば ) が表示されていることを意味します。
// 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 }