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(); }