安卓多层嵌套DialogFragment

4
我有一种场景,其中我展示一个使用getSupportFragmentManager()DialogFragment,它显示了一个值列表和一个“添加”按钮。如果用户点击添加按钮,我将显示另一个DialogFragment(使用getChildFragmentManager()),它由一个EditText和一个Button组成。当用户单击新的Button时,如果该值通过验证,则将其添加到列表中。如果未通过验证,则会显示另一个DialogFragment,其中显示错误消息和一个“OK”按钮。当单击“OK”按钮时,我想仍然让用户看到带有EditTextButtonDialogFragment,以便他们可以查看错误值并可能更改它。但是,在错误消息DialogFragment中按下“OK”按钮后,对话框会被关闭,只显示原始的DialogFragment (即带有值列表的那个)。
如何才能在第三个DialogFragment关闭后仍保留第二个DialogFragment的显示状态? 编辑: 这里是一些代码片段:
//clicking this button shows the first ("outer") fragment
findViewById(R.id.voicemail_notifications_email_addresses).setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            AddressListDialog.newInstance( 
                   line, AddressListDialog.VOICEMAIL_NOTIFICATIONS_EMAIL)
                  .show(((FragmentActivity)getContext()).getSupportFragmentManager(), "dialog");
        }

});

public static class AddressListDialog extends DialogFragment {
    public AddressListDialog() {}

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        final View v = LayoutInflater.from(getActivity()).inflate(R.layout.vm_address_list_dialog, null);
        ListView lv = (ListView) v.findViewById(R.id.voicemail_notifications_address_list);
        final AddressAdapter adapter = new AddressAdapter();
        lv.setAdapter(adapter);

        v.findViewById(R.id.voicemail_add_address_button).setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                //first child fragment
                AddAddressDialog.newInstance(getType()).setAdapter(adapter)
                                .show(getChildFragmentManager(), "dialog");
            }

        });

        Dialog d = new AlertDialog.Builder(getActivity())
                .setTitle(titleRes)
                .setView(v)
                .setPositiveButton(R.string.global_dialog_pos, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton) {
                            dialog.dismiss();
                        }
                    }
                )
                .create();
        return d;
    }

    private class AddressAdapter extends BaseAdapter {
        .
        .
        .
        public boolean add(LineVoicemailInfo.VmContact contact) {
            if(addresses.size() >= 3) {
                return false;
            }
            else if(!contact.isValid(isEmailType())) {
                return true;
            }
            else {
                addresses.add(contact);
                notifyDataSetChanged();
                return true;
            }
        }

public static class AddAddressDialog extends DialogFragment {
    private AddressAdapter adapter;

    public AddAddressDialog() {}

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        DialogInterface.OnClickListener onPosClick = null;

        final View v;
        v = LayoutInflater.from(getActivity()).inflate(R.layout.voicemail_add_email_address, null);
        onPosClick = new DialogInterface.OnClickListener() {                        
            @Override
            public void onClick(DialogInterface dialog, int which) {
                LineVoicemailInfo.VmContact contact = new LineVoicemailInfo.VmContact(((EditText)v.findViewById(R.id.voicemail_add_email_address)).getText().toString());
                if(!adapter.add(contact)) {
                    //second child fragment
                    BadAddressDialog.newInstance("Not a valid address")
                                    .show(getChildFragmentManager(), "dialog");
                }
            }
        };


        Dialog d = new AlertDialog.Builder(getActivity())
                .setTitle("Add Address")
                .setView(v)
                .setCancelable(false)
                .setPositiveButton(R.string.voicemail_addresses_add, onPosClick)
                .setNegativeButton(R.string.global_dialog_neg, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton) {
                           dialog.dismiss();
                        }
                })
                .create();
        setCancelable(false);
        return d;
    }
}

public static class BadAddressDialog extends DialogFragment {           
        public BadAddressDialog() {}

        public static BadAddressDialog newInstance(String message) {
            BadAddressDialog frag = new BadAddressDialog();
            Bundle args = new Bundle();
            args.putString("message", message);
            frag.setArguments(args);
            return frag;
        }

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {   
            String message = getArguments().getString("message");

            Dialog d = new AlertDialog.Builder(getActivity())
                    .setTitle("Error adding address")
                    .setMessage(message)
                    .setCancelable(false)
                    .setPositiveButton(R.string.global_dialog_pos, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton) {
                            dialog.dismiss();
                        }
                    })
                    .create();
            setCancelable(false);
            return d;
        }
    }

你介意展示相关的代码吗? - Stan
@Stan,请查看已编辑的问题。 - Eliezer
1
我猜问题可能在于您使用标准的 show 方法显示对话框。根据Android源代码,该方法不会将Fragment添加到backstack中,因此当最上面的对话框被解除时,中间的对话框也会被解除。在调用 show 之前,您应该自己开始处理事务,并将事务添加到backstack中(调用 addToBackStack)。示例可参考 DialogFragment文档页面 - Stan
@Stan,太好了!非常感谢。你想把它作为答案放在那里,这样我就可以给你吗? - Eliezer
1个回答

5
我想问题在于您使用标准的show方法显示对话框。根据Android源代码,该方法不会将片段添加到回退栈中,因此当顶部对话框被解除时,中间的对话框也会被解除。
在调用show之前,您应该自己开始事务,并将事务添加到回退栈(调用addToBackStack)。在DialogFragment文档页面上有一个示例。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接