web-dev-qa-db-ja.com

Android DialogFragmentは向きを変更すると消えます

私は2つのサイドバイサイド(Gmailのような)フラグメントを実装するFragmentActivityサポートv4クラスと、DialogFragmentを表示できるボタンを持っています。

向きを変えない限り、これはすべてうまくいきます。方向を変更すると、フラグメントの状態が保存されません。

そして、主な問題は、FragmentDialogを開いていると、単に消えてしまうことです。

すべてのフラグメントでsetRetainInstance(true);を設定しましたが、効果がありませんでした。

私のマニフェストにAndroid:configChanges="orientation"を含めましたが、まだ役に立ちません。

これが私のコードサンプルです、助けてくれてありがとう.

public class AddMasterDialog extends DialogFragment {

    private int mTitle;
    private int mPrompt;
    private OnClickListener onSaveListener;
    private OnClickListener onCancelListener;

    public AddMasterDialog newInstance(int title, int Prompt) {
        AddMasterDialog simpleDialog = new AddMasterDialog(title, Prompt);
        return simpleDialog;
    }

    public AddMasterDialog() {
        // Empty constructor required for DialogFragment
    }
    public AddMasterDialog(int title, int Prompt) {
        // Empty constructor required for DialogFragment
        mTitle = title;
        mPrompt = Prompt;
    }
    public void setSaveButton(OnClickListener save){
        onSaveListener = save;
    }
    public void setCancelButton(OnClickListener cancel){
        onCancelListener = cancel;
    }
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

        //if(savedInstanceState == null){
            View view = inflater.inflate(R.layout.add_new_simple, container);
            getDialog().setTitle(mTitle);
            ((TextView) view.findViewById(R.id.add_simple_new_value_Prompt)).setText(mPrompt);

            Button saveButton = (Button) view.findViewById(R.id.add_simple_save_button);
            saveButton.setOnClickListener(onSaveListener);

            //Cancel Button
            Button cancelButton = (Button) view.findViewById(R.id.add_simple_cancel_button);
            cancelButton.setOnClickListener(onCancelListener);
            return view;
        //}
    }
}

そして私のメイン活動で:

private void initiateAddMasterPopupWindow() {
        try {
            addMasterDialog = new AddMasterDialog(R.string.add_new_master_dialog_title, R.string.add_master_new_value_Prompt);
            addMasterDialog.setSaveButton(saveNewMasterClickListener);
            addMasterDialog.setCancelButton(cancelNewMasterClickListener);
            FragmentManager fm = getSupportFragmentManager();
            addMasterDialog.show(fm, ADD_NEW_MASTER);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
36
AlexIIP

さて、問題はDialogFragment互換性ライブラリにあるようです。

この問題は this の投稿で説明されています。

「フラグメントの廃止されたDISMISSメッセージはメッセージキューに保持されます。古いダイアログを閉じるときにDialogFragment.onDestroyView()によってキューに入れられ、新しいダイアログの作成後に再度アクティブになります。

迅速な(そしておそらくダーティーな)回避策は、onDestroyView()をオーバーライドし、super.onDestroyView()を呼び出す前に、dismissリスナーをクリアすることです。

次のコードをDialogFragmentに追加すると、問題が解決しました。

 @Override
 public void onDestroyView() {
     if (getDialog() != null && getRetainInstance()) {
         getDialog().setDismissMessage(null);
     }
     super.onDestroyView();
 }
73
AlexIIP

さまざまな理由で同じ問題を抱えている貧しい魂(私)のために、これを投稿します。次の操作を行う限り、ダイアログフラグメントは自動的に保存されます。

  1. Activity onSaveInstanceState()を呼び出す場合、スーパー関数を呼び出すことを確認してください!!!!です。私の場合、それが鍵でした。また、フラグメントで同じことを行うようにしてください。
  2. setRetainInstanceを使用する場合は、値を手動で保存して再適用する必要があります。それ以外の場合は、ほとんどの場合、それについて心配する必要はありません。もう少し複雑なことをしている場合は、setRetainInstance(true)が必要になることがありますが、それ以外の場合は無視してください。私の場合、クラスの1つにランダムシードを格納するためにそれを使用する必要がありましたが、それ以外は大丈夫でした。
  3. 一部の人々は、サポートライブラリのバグについて不満を言っています。最新のサポートライブラリで修正されているようですので、心配する必要はありません。

手動でフラグメントを保存するなど、特別なことをする必要はありません。次の手順に従うと、自動的に実行されます。全体として、これはより新しいサポートライブラリを持っている人にとってはうまくいくようです。

13
PearsonArtPhoto

私の場合、私はDialogFragmentを使用して別のDialogFragmentを表示していました

listDialogFragment.show(getChildFragmentManager(), "TAG");

に変更

listDialogFragment.show(getActivity().getSupportFragmentManager(), "TAG");

問題を修正しました

2
Maragues

setRetainInstance(true);の設定に加えて、次のコードをDialogFragmentに配置するだけです。テスト済みのソリューションです。

private boolean isDismissible = false;

@Override
public void dismiss() {

    try {

        isDismissible = true;
        super.dismiss();

        Log.d(getClass().getSimpleName(), "Dialog dismissed!");

    } catch (IllegalStateException ilse) {
    }
}

@Override
public void onDismiss(DialogInterface dialog) {

    // So that dialog should not dismiss on orientation change
    if (isDismissible) {

        // So that dialog can be dismissed
        super.onDismiss(dialog);
    }
}
1
Azmat Ali Khan