在DialogFragment中为AlertDialog增加自定义视图的问题

ash*_*hes 47 android android-inflate android-fragments layout-inflater android-alertdialog

我正在尝试DialogFragment使用自定义视图创建AlertDialog.必须从xml中扩充此视图.在我的DialogFragment班上,我有:

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    return new AlertDialog.Builder(getActivity())
        .setTitle("Title")
        .setView(getActivity().getLayoutInflater().inflate(R.layout.dialog, null))
        .setPositiveButton(android.R.string.ok, this)
        .setNegativeButton(android.R.string.cancel, null)
        .create();
}
Run Code Online (Sandbox Code Playgroud)

我尝试过其他通胀方法,.setView()例如:

.setView(getActivity().getLayoutInflater().inflate(R.layout.dialog, (ViewGroup) getView(), false))
Run Code Online (Sandbox Code Playgroud)

.setView(getActivity().getLayoutInflater().inflate(R.layout.dialog, (ViewGroup) getTargetFragment().getView(), false))
Run Code Online (Sandbox Code Playgroud)

在显示此对话框的片段中设置目标片段之后.

所有这些尝试使我的自定义视图膨胀都会导致以下异常:

E/AndroidRuntime(32352): android.util.AndroidRuntimeException: requestFeature() must be called before adding content
E/AndroidRuntime(32352):        at com.android.internal.policy.impl.PhoneWindow.requestFeature(PhoneWindow.java:214)
E/AndroidRuntime(32352):        at com.android.internal.app.AlertController.installContent(AlertController.java:248)
E/AndroidRuntime(32352):        at android.app.AlertDialog.onCreate(AlertDialog.java:314)
E/AndroidRuntime(32352):        at android.app.Dialog.dispatchOnCreate(Dialog.java:335)
E/AndroidRuntime(32352):        at android.app.Dialog.show(Dialog.java:248)
E/AndroidRuntime(32352):        at android.support.v4.app.DialogFragment.onStart(DialogFragment.java:339)
E/AndroidRuntime(32352):        at android.support.v4.app.Fragment.performStart(Fragment.java:1288)
E/AndroidRuntime(32352):        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:873)
E/AndroidRuntime(32352):        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1041)
E/AndroidRuntime(32352):        at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:625)
E/AndroidRuntime(32352):        at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1360)
E/AndroidRuntime(32352):        at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:411)
E/AndroidRuntime(32352):        at android.os.Handler.handleCallback(Handler.java:587)
E/AndroidRuntime(32352):        at android.os.Handler.dispatchMessage(Handler.java:92)
E/AndroidRuntime(32352):        at android.os.Looper.loop(Looper.java:132)
E/AndroidRuntime(32352):        at android.app.ActivityThread.main(ActivityThread.java:4028)
E/AndroidRuntime(32352):        at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(32352):        at java.lang.reflect.Method.invoke(Method.java:491)
E/AndroidRuntime(32352):        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:844)
E/AndroidRuntime(32352):        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
E/AndroidRuntime(32352):        at dalvik.system.NativeStart.main(Native Method)
Run Code Online (Sandbox Code Playgroud)

而如果我尝试使用DialogFragmentgetLayoutInflator(Bundle)是这样的:

.setView(getLayoutInflater(savedInstanceState).inflate(R.layout.dialog, null))
Run Code Online (Sandbox Code Playgroud)

我得到了StackOverflowError.

有谁知道如何膨胀的自定义视图的AlertDialog一个DialogFragment

Pro*_*man 88

第一个错误行给了我一个暗示,这与你如何创建对话框有关 - 而不是对话框本身.

您是自动创建对话框(可能意味着在视图全部设置之前调用此对话框)还是响应按钮单击?由于实例化顺序,我最初遇到碎片问题.

我使用相同的代码来设置视图,我的结果是有效的.我删除了其他设置,使其看起来更干净,但无论是否有效都可以.

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

    View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_layout, null);
    builder.setView(view);

    return builder.create();
}
Run Code Online (Sandbox Code Playgroud)

  • 这让我想到了一个真正的问题,那就是你必须在其他任何东西之前调用`setView()`(比如`setTitle()`,这就是我做错了).谢谢. (16认同)
  • 这对我有用,但我想了解原因。为什么dialogFragment的getLayoutInflater返回与Activity不同的layoutinflater? (2认同)

van*_*rra 23

我对这些答案感到惊讶,因为他们都没有解决问题.

DialogFragment允许您为对话框重用相同的UI,并将其作为片段集成到您的应用程序中.相当有用的功能.根据谷歌的文档,你可以通过覆盖onCreateDialog和onCreateView来实现这一点. http://developer.android.com/reference/android/app/DialogFragment.html

这里有三种情况:

  1. 仅覆盖onCreateDialog - 作为对话框工作,但不能在其他地方集成.
  2. 仅覆盖onCreateView - 不能用作对话框,但可以集成到其他位置.
  3. 覆盖两者 - 作为对话框工作,可以集成到其他地方.

解决方案:AlertDialog类正在调用另一个调用requestFeature的类.解决这个问题.不要使用AlertDialog,而是使用普通的Dialog或super.onCreateDialog返回的任何内容.这个我找到的解决方案效果最好.

警告:其他对话框,如DatePickerDialog,ProgressDialog,TimePickerDialog都继承自AlertDialog,可能会导致相同的错误.

结论:如果您需要创建需要在多个地方使用的非常自定义的界面,DialogFragment是很好的.它似乎无法重用现有的android对话框.


小智 11

避免请求功能崩溃并使用相同的布局:

public class MyCombinedFragment extends DialogFragment
{
    private boolean isModal = false;

    public static MyCombinedFragment newInstance()
    {
        MyCombinedFragment frag = new MyCombinedFragment();
        frag.isModal = true; // WHEN FRAGMENT IS CALLED AS A DIALOG SET FLAG
        return frag;
    }

    public MyCombinedFragment()
    {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
    {
        if(isModal) // AVOID REQUEST FEATURE CRASH
        {
        return super.onCreateView(inflater, container, savedInstanceState);
        }
        else
        {
        View view = inflater.inflate(R.layout.fragment_layout, container, false);
        setupUI(view);
        return view;
        }
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState)
    {
        AlertDialog.Builder alertDialogBuilder = null;
        alertDialogBuilder = new AlertDialog.Builder(getActivity());
        View view = getActivity().getLayoutInflater().inflate(R.layout.fragment_layout, null);
        alertDialogBuilder.setView(view);
        alertDialogBuilder.setTitle(“Modal Dialog“);
        alertDialogBuilder.setPositiveButton("Cancel", new DialogInterface.OnClickListener()
        {
            @Override
            public void onClick(DialogInterface dialog, int which)
            {
                dialog.dismiss();
            }
        });
        setupUI(view);
        return alertDialogBuilder.create();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 仅供参考,您可以使用`getShowsDialog()`来了解您的片段是否显示为模态.但看看@vangorra的回答. (3认同)