2012年7月9日月曜日

DialogFragmentメモ(2)

前回の結論として、DialogFragmentのonCreateView()よりonCreateDialog()をOverrideした方が良さそうだったのでやってみたメモ。

注意(2012/07/09追記)
ダイアログ表示状態で画面を回転してダイアログのボタンを押すとNullPointerExceptionで落ちることに気付きました...
落ちる場所はDialogButtonClickListenerの65行目からのif文でどちらのダイアログか判別している部分です。
修正してブログ更新する予定。。

DialogFragmentメモ
http://neta-abc.blogspot.jp/2012/06/dialogfragment.html




ただ、DialogFragmentのonCreateDialog()の中で表示内容を設定してしまうとダイアログの数だけDialogFragmentを継承したクラスを作らないといけないので、今回はDialogFragmentを継承したクラスを1つ作り、それを使い回せるようにすることを目標にやってみました。

方針(ざっくり)
(1) DialogFragmentを継承したAlertDialogFragmentクラスを作成する
(2) ダイアログ表示内容の設定はダイアログの呼び出し元で行う
(3) (2)で作成したダイアログ表示内容をsetArguments()でFragmentに設定する
(4) AlertDialogFragmentのonCreateDialog()をOverrideして、(3)で設定したダイアログの表示内容をAlertDialogFragmentに反映する

といったところです。

ただし、setArguments()を使ってFragmentに渡せる引数はBundle型なので、AlertDialog.Builderを継承したクラスを作成してSerializableインターフェースを実装しています。※BundleのputSerializable()を使うためです。

コード
MainActivity.java
package com.example.alertdialogfragment;

import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Toast;

public class MainActivity extends FragmentActivity implements OnClickListener {

    private AlertDialogFragment mDialogFragment1;
    private AlertDialogFragment mDialogFragment2;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findViewById(R.id.button1).setOnClickListener(this);
        findViewById(R.id.button2).setOnClickListener(this);
    }

    public void onClick(View view) {
        DialogButtonClickListener listener = new DialogButtonClickListener();
        AlertDialogFragment.Builder builder = new AlertDialogFragment.Builder(this);
        Bundle params = new Bundle();

        switch (view.getId()) {
            case R.id.button1:
                builder.setTitle("Title1");
                builder.setMessage("Message1");
                builder.setPositiveButton("POSITIVE", listener);
                builder.setNeutralButton("NEUTRAL", listener);
                builder.setNegativeButton("NEGATIVE", listener);

                params.putSerializable("builder", builder);

                mDialogFragment1 = new AlertDialogFragment();
                mDialogFragment1.setArguments(params);
                mDialogFragment1.setCancelable(false);
                mDialogFragment1.show(getSupportFragmentManager(), "dialog1");
                break;
            case R.id.button2:
                builder.setTitle("Title2");
                builder.setMessage("Message2");
                builder.setPositiveButton("POSITIVE", listener);
                builder.setNeutralButton("NEUTRAL", listener);
                builder.setNegativeButton("NEGATIVE", listener);

                params.putSerializable("builder", builder);

                mDialogFragment2 = new AlertDialogFragment();
                mDialogFragment2.setArguments(params);
                mDialogFragment2.setCancelable(false);
                mDialogFragment2.show(getSupportFragmentManager(), "dialog2");
                break;
        }
    }

    private class DialogButtonClickListener implements DialogInterface.OnClickListener {
        public void onClick(DialogInterface dialog, int which) {
            String dialogName = "";
            if (dialog.equals(mDialogFragment1.getDialog())) {
                dialogName = "ダイアログ1";
            } else if (dialog.equals(mDialogFragment2.getDialog())) {
                dialogName = "ダイアログ2";
            }
            switch (which) {
                case DialogInterface.BUTTON_POSITIVE:
                    Toast.makeText(getApplicationContext(), dialogName + ":POSITIVE",
                            Toast.LENGTH_SHORT).show();
                    break;
                case DialogInterface.BUTTON_NEUTRAL:
                    Toast.makeText(getApplicationContext(), dialogName + ":NEUTRAL",
                            Toast.LENGTH_SHORT).show();
                    break;
                case DialogInterface.BUTTON_NEGATIVE:
                    Toast.makeText(getApplicationContext(), dialogName + ":NEGATIVE",
                            Toast.LENGTH_SHORT).show();
                    break;
            }
        }
    }
}
AlertDialogFragment.java
package com.example.alertdialogfragment;

import java.io.Serializable;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;

public class AlertDialogFragment extends DialogFragment {

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        Bundle params = getArguments();
        AlertDialog.Builder builder = (AlertDialog.Builder) params.getSerializable("builder");
        return builder.create();
    }

    public static class Builder extends AlertDialog.Builder implements Serializable {

        private static final long serialVersionUID = 1L;

        public Builder(Context context) {
            super(context);
        }

        public Builder(Context context, int theme) {
            super(context, theme);
        }

    }

}

Cancelableの設定はAlertDialog.Bulderではなく、DialogFragmentのsetCancelabre()を使うので注意です。ちょっとはまりました...
DialogFragmentを使うと画面を回転したときにダイアログを再表示してくれるので良いですね。

FragmentのsetArguments()については、ここを参考にしました。
Y.A.M の 雑記帳
Fragment で setArguments() してるサンプルが多いのはなぜ?
http://y-anz-m.blogspot.jp/2012/04/androidfragment-setarguments.html

0 件のコメント:

コメントを投稿