Пользовательский макет для DialogFragment OnCreateView против OnCreateDialog
Я пытаюсь создать DialogFragment, используя свой собственный макет.
Я видел несколько разных подходов. Иногда макет находится в OnCreateDialog такой: (Я использую Mono, но я немного привык к 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.
поэтому после небольшого поиска я попробовал второй подход, который включает переопределение OnCreateView
поэтому я прокомментировал две строки OnCreateDialog
что установить Макет, а затем добавил Это:
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
Я в тупике.
6 ответов
Это первый подход работает для меня... пока я не захочу использовать FindViewByID.
Я бы предположил, что вы не scoping findViewById()
в представление, возвращаемое inflate()
, попробуйте это:
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;
}
}
вы должны выбрать, чтобы переопределить единственный onCreateView или onCreateDialog в DialogFragment. Переопределение обоих приведет к исключению: "requestFeature () должен быть вызван перед добавлением содержимого".
важно
для полного ответа проверьте комментарий @TravisChristian. Как он сказал, Вы можете переопределить оба действительно, но проблема возникает, когда вы пытаетесь раздуть представление после создания диалогового окна.
ниже код приходит из Google guide, поэтому ответ заключается в том, что вы не могли бы сделать, как ваш в 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();
}
Как говорит @Xavier Egea, если у вас реализованы onCreateView() и onCreateDialog (), вы рискуете получить сбой "requestFeature() должен быть вызван перед добавлением содержимого". Это потому, что оба onCreateDialog() затем onCreateView() вызываются, когда вы показываете() этот фрагмент как диалог (Почему, я не знаю). Как упоминал Трэвис Кристиан, inflate () в onCreateView () после создания диалога в onCreateDialog () является причиной сбоя.
один путь к реализуйте обе эти функции, но избегайте этого сбоя: используйте getShowsDialog (), чтобы ограничить выполнение вашего onCreateView () (поэтому ваш inflate () не вызывается). Таким образом, только ваш код onCreateDialog() выполняется при отображении Вашего DialogFragment в виде диалога, но ваш код onCreateView() может быть вызван, когда ваш DialogFragment используется как фрагмент в макете.
// 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;
}
Если вы хотите иметь легкий доступ к свойствам диалогового окна, как заголовок и кнопка уволить, но вы также хотите использовать свой собственный макет, вы можете использовать LayoutInflator с вашим строителем при переопределении onCreateDialog.
@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();
}