膨胀视图onCreateView自定义DialogFragment导致AndroidRuntimeException

时间:2014-01-10 09:50:49

标签: android android-fragments

关于android.util.AndroidRuntimeException: requestFeature() must be called before adding content的问题有很多。但是所提出的解决方案都没有对我有用。

我有自定义DialogFragment

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    return new AlertDialog.Builder(getActivity()).create();
}

@Override
public final View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    return inflater.inflate(R.layout.notification_dialog, null);
}

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    //setting up dialog
}

我这样表现出来 newDialogInstance().show(activity.getFragmentManager(), "tag-dialog-fragment");

每次我得到:

android.util.AndroidRuntimeException: requestFeature() must be called before adding content
            at com.android.internal.policy.impl.PhoneWindow.requestFeature(PhoneWindow.java:226)
            at com.android.internal.app.AlertController.installContent(AlertController.java:234)
            at android.app.AlertDialog.onCreate(AlertDialog.java:337)
            at android.app.Dialog.dispatchOnCreate(Dialog.java:355)
            at android.app.Dialog.show(Dialog.java:260)
            at android.app.DialogFragment.onStart(DialogFragment.java:490)
            at android.app.Fragment.performStart(Fragment.java:1719)

有人可以解释一下这里发生了什么吗?

3 个答案:

答案 0 :(得分:3)

这是一个迟到的答案,但也许可以帮助某人,问题来自于您试图从onCreateDialogonCreateView充气对话这一事实。为避免这种情况,您可以避免使用onCreateView并在onCreateDialog中扩充您的布局。

你会得到这个:

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    // Get the layout inflater
    LayoutInflater inflater = getActivity().getLayoutInflater();
    View layout = inflater.inflate(R.layout.notification_dialog, null);

    /** Add modifications on your layout if needed */

    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    // Add your custom layout to the builder
    builder.setView(layout);

    return builder.create();
}

然后只需删除onCreateView或使用它来执行其他操作,例如使用savedInstanceState,如其他答案中所述:https://stackoverflow.com/a/15602648/2206688

您还可以查看文档示例: http://developer.android.com/guide/topics/ui/dialogs.html#CustomLayout

答案 1 :(得分:3)

另一个迟到的答案我把它的一部分作为评论写了但也许它对其他人也很有用。

正如Yoann已经写过的,问题是View被创建了两次,在对话框中,它创建了自己的窗口,导致了问题。官方文档(http://developer.android.com/reference/android/app/DialogFragment.html#AlertDialog)使得似乎可以同时覆盖onCreateViewonCreateDialog并显示可以嵌入或使用的自定义布局AlertDialog样式:< / p>

  

而不是(或除此之外)实施   onCreateView(LayoutInflater,ViewGroup,Bundle)生成视图   对话框内的层次结构,你可以实现onCreateDialog(Bundle)   创建自己的自定义Dialog对象。

     

这对于创建AlertDialog,[...]

非常有用

可以覆盖这两种方法,但不能与AlertDialog.Builder结合使用。

到目前为止,对我有用的是:

public class CustomDialogFragment extends DialogFragment {

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        if (isInLayout())
            return super.onCreateDialog(savedInstanceState);

        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
                .setView(R.layout.my_custom_layout)
                .setTitle(R.string.my_title)
                .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        // TODO implement
                    }
                });

        return builder.create();
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        if (!isInLayout())
            return super.onCreateView(inflater, container, savedInstanceState);

        View v = inflater.inflate(R.layout.my_custom_layout, container);
        return v;
    }
}

我使用isInLayout()来决定是调用超级方法还是使用自定义实现。

编辑:此示例使用支持库类:http://developer.android.com/reference/android/support/v7/app/AlertDialog.Builder.html#setView(int)

答案 2 :(得分:-8)

像这样使用:

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
View view = getActivity().getLayoutInflater().inflate(R.layout.notification_dialog, null);
builder.setView(view);
return builder;
}