DialogFragment的自定义布局OnCreateView与OnCreateDialog

我试图创build一个DialogFragment使用我自己的布局。

我见过几种不同的方法。 有时候,布局是这样设置的OnCreateDialog :(我使用单声道,但我已经习惯了Java)

public override Android.App.Dialog OnCreateDialog (Bundle savedInstanceState) { base.OnCreateDialog(savedInstanceState); AlertDialog.Builder b = new AlertDialog.Builder(Activity); //blah blah blah LayoutInflater i = Activity.LayoutInflater; b.SetView(i.Inflate(Resource.Layout.frag_SelectCase, null)); return b.Create(); } 

这第一种方法适用于我…直到我想使用findViewByID. 所以经过一番search后,我尝试了第二种方法,其中涉及覆盖OnCreateView

所以我注释了两行OnCreateDialog ,它们设置了Layout,然后添加了这个:

 public override Android.Views.View OnCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.Inflate(Resource.Layout.frag_SelectCase, container, false); //should be able to use FindViewByID here... return v; } 

这给了我一个可爱的错误:

 11-05 22:00:05.381: E/AndroidRuntime(342): FATAL EXCEPTION: main 11-05 22:00:05.381: E/AndroidRuntime(342): android.util.AndroidRuntimeException: requestFeature() must be called before adding content 

我很难过

这第一种方法适用于我…直到我想使用FindViewByID。

我猜你不是范围findViewById()到由findViewById()返回的视图,试试这个:

 View view = i.inflate(Resource.Layout.frag_SelectCase, null); // Now use view.findViewById() to do what you want b.setView(view); return b.create(); 

我有以下代码的例外:

 public class SelectWeekDayFragment extends DialogFragment { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { return new AlertDialog.Builder(getActivity()) .setMessage("Are you sure?").setPositiveButton("Ok", null) .setNegativeButton("No way", null).create(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.week_day_dialog, container, false); return view; } } 

您必须select覆盖DialogFragment中的onCreateView或onCreateDialog中的一个。 重写这两个将导致exception:“添加内容之前必须调用requestFeature()”。

重要

要获得完整的答案,请查看@TravisChristian评论。 正如他所说的,你可以重写两者,但是当你在创build对话视图之后尝试膨胀视图时会出现问题。

下面的代码来自谷歌指南,所以答案是,你不能像你的onCreateDialog(),你必须使用super.onCreateDialog()来获得一个对话框。

 public class CustomDialogFragment extends DialogFragment { /** The system calls this to get the DialogFragment's layout, regardless of whether it's being displayed as a dialog or an embedded fragment. */ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout to use as dialog or embedded fragment return inflater.inflate(R.layout.purchase_items, container, false); } /** The system calls this only when creating the layout in a dialog. */ @Override public Dialog onCreateDialog(Bundle savedInstanceState) { // The only reason you might override this method when using onCreateView() is // to modify any dialog characteristics. For example, the dialog includes a // title by default, but your custom layout might not need it. So here you can // remove the dialog title, but you must call the superclass to get the Dialog. Dialog dialog = super.onCreateDialog(savedInstanceState); dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); return dialog; } } 

这是在对话框片段中使用findViewById的一个例子

 public class NotesDialog extends DialogFragment { private ListView mNotes; private RelativeLayout addNote; public NotesDialog() { // Empty constructor required for DialogFragment } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); View view = getActivity().getLayoutInflater().inflate(R.layout.note_dialog, null); mNotes = (ListView) view.findViewById(R.id.listViewNotes); addNote = (RelativeLayout) view.findViewById(R.id.notesAdd); addNote.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v){ getDialog().dismiss(); showNoteDialog(); } }); builder.setView(view); builder.setTitle(bandString); builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { getDialog().dismiss(); } } ); return builder.create(); } 

正如Freerider所说,如果你同时实现了onCreateView()和onCreateDialog(),那么你就有可能在添加内容之前调用“requestFeature()”。 这是因为onCreateDialog(),然后onCreateView()当你show()片段作为一个对话框(为什么,我不知道)调用。 正如Travis Christian所提到的,在onCreateDialog()中创build对话框之后的onCreateView()中的inflate()是导致崩溃的原因。

一种方法来实现这两个函数,但避免这个崩溃:使用getShowsDialog()来限制您的onCreateView()(所以你的inflate()不被调用)的执行)。 通过这种方式,只有当您将DialogFragment显示为对话框时,才会执行onCreateDialog()代码,但是在将DialogFragment用作布局中的片段时,可以调用onCreateView()代码。

 // Note: if already have onCreateDialog() and you only ever use this fragment as a // dialog, onCreateView() isn't necessary @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { if (getShowsDialog() == true) { // **The key check** return super.onCreateView(inflater, container, savedInstanceState); } else { View view = getActivity().getLayoutInflater().inflate(R.layout.fragment_alarm_dialog, null); return configureDialogView(view); } } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { // Return custom dialog... Dialog dialog = super.onCreateDialog(savedInstanceState); // "new Dialog()" will cause crash View view = getActivity().getLayoutInflater().inflate(R.layout.fragment_alarm_dialog, null); configureDialogView(view); dialog.setContentView(view); return dialog; } // Code that can be reused in both onCreateDialog() and onCreateView() private View configureDialogView(View v) { TextView myText = (TextView)v.findViewById(R.id.myTextView); myText.setText("Some Text"); // etc.... return v; } 

如果您希望轻松访问对话属性(如标题和解除button),但也想使用自己的布局,则可以在覆盖onCreateDialog时使用LayoutInflator和Builder。

 @Override public Dialog onCreateDialog(Bundle savedInstanceState) { LayoutInflater inflater = getActivity().getLayoutInflater(); AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setMessage("Message!") .setTitle(this.dialogTitle) .setView(inflater.inflate(R.layout.numpad_dialog, null)) .setPositiveButton(R.string.enter, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // Clicked 'Okay' } }) .setNegativeButton(R.string.dismiss, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // Clicked 'Cancel' } }); return builder.create(); }