2012年8月4日土曜日

ダイアログが重ならないように制御する

チームEGGの曽川です。

DialogFragmentを表示する場合、複数のDialogFragmentが重なって表示される場合があります。ボタンを連打してダイアログを表示した場合などです。
情報を表示するだけのダイアログであれば良いのですが、何かを選択したり、一度しか行いたくない処理の場合は、複数表示されることが不都合なことがあります。
GoogleMapsではこのような場合に、連打されたら一度消去して再度表示するような動作をしていたので、その方法を実装しました。
public class ExclusiveDialogFragment extends DialogFragment {

    /** ダイアログの共通タグ */
    private static final String TAG = "exclusive_dialog";

    /**
     * タグ指定不可のため、直接の呼び出しは非推奨です。
* {@link #show(FragmentManager)}を利用してください。
     */
    @Deprecated
    @Override
    public final void show(final FragmentManager manager, final String tag) {
        show(manager);
    }

    /**
     * ダイアログを表示します。
     * 
     * @param manager
     *            {@link FragmentManager}
     */
    public void show(final FragmentManager manager) {
        deleteDialogFragment(manager);
        super.show(manager, TAG);
    }

    /**
     * すでに表示されたダイアログを消去します
     * 
     * @param fragmentManager
     *            {@link FragmentManager}
     */
    private static void deleteDialogFragment(final FragmentManager fragmentManager) {

        final ExclusiveDialogFragment prev = (ExclusiveDialogFragment) fragmentManager.findFragmentByTag(TAG);
        // フラグメントが表示されていなければ処理なし
        if (prev == null) {
            return;
        }

        final Dialog dialog = prev.getDialog();
        // ダイアログがなければ処理なし
        if (dialog == null) {
            return;
        }

        // ダイアログが表示されていなければ処理なし
        if (!dialog.isShowing()) {
            return;
        }

        // ダイアログ消去通知と消去
        prev.onDismissExclusiveDialog();
        prev.dismiss();
    }

    /**
     * ダイアログが排他的消去される際に呼び出されます。
     */
    protected void onDismissExclusiveDialog() {
        // 継承先で処理を実装
    }

}
まず、DialogFragmentを表示するタグを固定します。
/** ダイアログの共通タグ */
    private static final String TAG = "exclusive_dialog";
すでにダイアログが表示されていれば、そのタグを使ってダイアログを削除します。
private void deleteDialogFragment(final FragmentManager fragmentManager) {
    final ExclusiveDialogFragment prev = (ExclusiveDialogFragment) fragmentManager.findFragmentByTag(TAG);
      ...
    prev.dismiss();
}
このクラスを継承してDialogFragmentを使用しますが、タグを固定しているので通常の呼び出し方法ではなく以下のメソッドを使います。(※show(FragmentManager manager,String tag)もタグは無視されますが使用できるようにはしています。)
public void show(final FragmentManager manager){}
これで、ダイアログが複数表示されなくなります。
また事前にフラグメントに処理を行いたい際には、onDismissExclusiveDialogをオーバライドして処理を記述します。

0 件のコメント:

コメントを投稿