28

いくつかのアイテムのリストを表示する単純なAlertDialogものがあり、そのうちの1つをクリックすると、クリックされたアイテムが囲んでいる に返されますActivityまた、ユーザーが (戻るボタンを使用して) ダイアログをキャンセルしたときに、いくつかのデフォルト処理を実行したいと考えています。より具体的には、そのような場合に空の文字列をアクティビティに渡したいと考えています。

ただし、ダイアログをDialogFragment(互換パッケージから) に配置するOnCancelListener と、戻るボタンでダイアログを閉じたときに が呼び出されません。私は何を間違っていますか?

public class SelectItemDialog extends DialogFragment {

    public interface Callback {
        void onItemSelected(String string);
    }

    private static final String ARG_ITEMS = "items";

    private Callback callback;

    public static SelectItemDialog fromItems(Collection<String> items) {
        SelectItemDialog fragment = new SelectItemDialog();
        fragment.setArguments(newArguments(items));
        return fragment;
    }

    private static Bundle newArguments(Collection<String> items) {
        Bundle arguments = new Bundle();
        arguments.putStringArray(ARG_ITEMS, items.toArray(new String[items.size()]));
        return arguments;
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        callback = (Callback) activity;
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        final String[] items = getArguments().getStringArray(ARG_ITEMS);
        return new AlertDialog.Builder(getActivity())
            .setTitle(R.string.dialog_select_email_title)
            .setItems(items, new OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    callback.onItemSelected(items[which]);
                }
            })
            .setOnCancelListener(new OnCancelListener() {
                @Override
                public void onCancel(DialogInterface dialog) {
                    // this code is not executed
                    callback.onItemSelected("");
                    throw new RuntimeException("dialog cancelled");
                }
            })
            .create();
    }
}
4

5 に答える 5

54

コードからの明示的な呼び出しがないという事実に関係している可能性がありcancel()ます。OnCancelListenerのドキュメントには次 のように書かれています。

これは、ダイアログがキャンセルされたときにのみ呼び出されます

おそらく明示的なcancel()呼び出しが必要です。

OnClickListenerを呼び出すポジティブ/ネガティブ ボタンを作成するか、追加のチェックをDialogInterface#cancel()使用しOnDismissListener()てリスト項目がクリックされたかどうかを確認します。

また、戻るキーの押下をリッスンしてダイアログをキャンセルするには、このSOの回答OnKeyListenerで概説されているように、を設定できます

また、ダイアログを設定したらDialog#setCanceledOnTouchOutside()、ユーザーがダイアログの外をタップした場合にも使用することをお勧めします。

編集: 以下の部分は、DialogFragment でキャンセル イベントを処理する簡単な方法です。

を使用しているためDialogFragment、このクラスには非常に便利なメソッドがあり、がキャンセルされDialogFragment#onCancel()たときに呼び出されます。DialogFragmentそこでロジックを実行します。

DialogFragments はより複雑で、通常のダイアログとはライフサイクルがわずかに異なります。したがって、Dialogに移植しようとしている特定の に基づくアプローチがある場合は、最初にドキュメントを確認しDialogFragmentてください。新しい実装を適切に機能させる方法がいくつか存在する可能性があります。

于 2013-02-09T16:31:28.190 に答える
12

DialogFragmentを使用していて、戻るボタンを聞きたい場合は、これを使用します -

    this.getDialog().setOnKeyListener(new Dialog.OnKeyListener() {
        @Override
        public boolean onKey(DialogInterface dialog, int keyCode,
                KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                if (****) {
                    your logic
                }
                return true;
            }
            return false;
        }
    });
于 2013-09-09T18:16:52.517 に答える
11

注: DialogFragment は、Dialog.setOnCancelListener および Dialog.setOnDismissListener コールバックを所有しています。自分で設定しないでください。

これらのイベントについて調べるには、onCancel(DialogInterface) と onDismiss(DialogInterface) をオーバーライドします。

public class SelectItemDialog extends DialogFragment {

    @Override
    public void onDismiss(DialogInterface dialog) {
        super.onDismiss(dialog);
        //your code hear
        dialog.cancel();
    }
}

そして、 .setOnCancelListener() を削除する必要があります

于 2015-12-29T10:53:38.740 に答える
1

実際に を使用したい場合は、ダイアログ フラグメントがこれらのメソッドへのコールバックを所有しているため、またはをDialogFragment追加することはできません!OnCancelListenerOnDismissListener

ここには 3 つのオプションがあります。

1- 通常のダイアログを使用します。
2- ダイアログ フラグメントをキャンセル可能 (false) に設定し、キャンセル ボタンをダイアログに追加します。
3-@Nikhil Pingleの回答を確認してください。

これはDialog Fragmentのドキュメントからのものです

 * <p><em>Note: DialogFragment own the {@link Dialog#setOnCancelListener
 * Dialog.setOnCancelListener} and {@link Dialog#setOnDismissListener
 * Dialog.setOnDismissListener} callbacks.  You must not set them yourself.</em>
 * To find out about these events, override {@link #onCancel(DialogInterface)}
 * and {@link #onDismiss(DialogInterface)}.</p>
于 2014-09-25T03:01:20.873 に答える