2012-06-14 10 views
12

私はサードパーティ製のライブラリを使用していますが、ダイアログが表示されることがあります。現在のアクティビティを終了する前に、現在のコンテキストでダイアログがポップアップしているかどうか確認したいと思います。現在のアクティビティにダイアログが表示されているかどうかを確認するにはどうすればよいですか?

APIはありますか?

+1

どのようなサードパーティライブラリを使用していますか、どのような種類のアプリケーションを使用していますか? –

答えて

7

AFAIK - このための公開APIはありません。

お勧めの方法は、ダイアログボックスを参照し、isShowing()を確認し、必要に応じてdismiss()を呼び出しますが、サードパーティのライブラリを使用しているため、これはオプションではない可能性があります。

お使いのライブラリのドキュメントを確認することをお勧めします。それが助けにならないなら、あなたは運がない。

ヒント:ダイアログがポップアップすると、アクティビティが「一時停止」状態に切り替わります。

+0

onpauseのダイアログIDには何もありませんか? – newme

+1

ええええええええ、あなたの問題を見る... onCreateDialogメソッドをオーバーライドすることができます。現在開いているダイアログのIDのリストを維持し、終了するときに閉じなければなりません。使用しているライブラリがそれをサポートしていない場合にのみ、このメソッドを使用してください。予期せずダイアログを閉じると、サードパーティライブラリから問題が発生する可能性があります。 (nullポインタfun) – Madushan

+0

また、このメソッドとdismissDialogメソッドは、Fragmentパターンの方が推奨されていません。だから私はそれが最良のアプローチだとは言いません。そして、ダイアログが閉じたときに検出できないように見えます(ただし、アクティビティが一時停止から復帰したときにはそれを仮定することができますが、画面から再開したときに復帰することを確認してください)。ですから、既知のすべてのダイアログ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

Dismissed DialogFragmentはFragmentManagerから削除されます – twlkyao

+0

dismissInternalのpopとmoveの瞬間が表示されますが、 getFragmentsは、同じライブラリグループ内からのみ呼び出すことができます。ルートビュー(DecorView)から – twlkyao

1

私が想定しています、あなたが扱っていますサードパーティのライブラリであり、ダイアログオブジェクトへのアクセス権がありません。

あなたは、その後、あなたが子ビューのいずれかに達することができるかどうかを確認するために、ツリートラバーサルアルゴリズムを使用することができ、活動から

をルートビューを取得することができます。警告ボックスが表示されている場合は、子ビューには到達しないでください。

アラートビューが表示されたとき(Ui Automatorでチェック)、UIツリーにある唯一の要素はDialogBox/DialogActivityです。このトリックを使用して、ダイアログが画面に表示されているかどうかを確認することができます。高価に思えますが、最適化することができます。

+0

を選択すると、そのダイアログは別のウィンドウに表示されるため、ダイアログには到達できません。私が行うことができるのは、 'mPrivateFlags'と異なる唯一のメンバであるDecorVieアクセスからです。ダイアログが開いているときに' 25201976'から '29363512'になります。次の仕事はここから適切な有用なフラグを見つけることですhttps://github.com/android/platform_frameworks_base/blob/master/core/java/android/view/View.java#L1737は堅くなければなりません –

+0

hmm、多分 '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'は_first_時間を返しますが、アクティビティについてはダイアログに表示されますが、それ以降の時間は表示されないようです。私は掘り続けます。 – VicVu