Próbuję utworzyć DialogFragment przy użyciu mojego własnego układu.
Widziałem kilka różnych podejść. Czasami układ jest ustawiany w OnCreateDialog w następujący sposób: (używam Mono, ale trochę przyzwyczaiłem się do 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();
}
To pierwsze podejście działa dla mnie ... dopóki nie chcę go użyć, findViewByID.
więc po chwili googlowania wypróbowałem drugie podejście, które obejmuje nadpisywanieOnCreateView
Skomentowałem więc dwie linie OnCreateDialog
tego zestawu Układu, a następnie dodałem to:
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;
}
co daje mi piękny błąd:
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
Jestem zdumiony.
java
android
mono
xamarin.android
android-inflate
gghuffer
źródło
źródło
Odpowiedzi:
Przypuszczam, że nie sięgasz
findViewById()
do widoku zwróconego przezinflate()
, spróbuj tego:View view = i.inflate(Resource.Layout.frag_SelectCase, null); // Now use view.findViewById() to do what you want b.setView(view); return b.create();
źródło
requestFeature(...)
(lub coś podobnegorequestWindowFeature(Window.FEATURE_NO_TITLE);
) po dodaniu treści (na przykład komunikat o wyjątku już stwierdza).Miałem ten sam wyjątek z następującym kodem:
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; } }
Musisz wybrać nadpisanie tylko jednego z onCreateView lub onCreateDialog w DialogFragment. Zastępowanie obu spowoduje wyjątek: „requestFeature () należy wywołać przed dodaniem treści”.
Ważny
Pełną odpowiedź znajdziesz w komentarzu @TravisChristian. Jak powiedział, możesz rzeczywiście przesłonić oba, ale problem pojawia się, gdy spróbujesz zawęzić widok po utworzeniu już widoku dialogowego.
źródło
Poniższy kod pochodzi z przewodnika Google, więc odpowiedź jest taka, że nie możesz polubić swojego w onCreateDialog (), musisz użyć super.onCreateDialog (), aby uzyskać okno dialogowe.
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; } }
źródło
onCreateDialog()
metodzie. CzyonCreateView()
pomoże w tym przypadku?Oto przykład użycia findViewById we fragmencie okna dialogowego
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(); }
źródło
Jak mówi @Xavier Egea, jeśli masz zaimplementowane zarówno onCreateView (), jak i onCreateDialog (), istnieje ryzyko wystąpienia awarii „requestFeature ()”, która musi zostać wywołana przed dodaniem zawartości. Dzieje się tak, ponieważ ZARÓWNO onCreateDialog (), jak i onCreateView () są wywoływane, gdy pokazujesz () ten fragment jako okno dialogowe (dlaczego, nie wiem). Jak wspomniał Travis Christian, inflate () w onCreateView () po utworzeniu okna dialogowego w onCreateDialog () powoduje awarię.
Jeden ze sposobów na zaimplementowanie obu tych funkcji, ale uniknięcie tej awarii: użyj getShowsDialog (), aby ograniczyć wykonywanie onCreateView () (aby funkcja inflate () nie była wywoływana). W ten sposób tylko kod onCreateDialog () jest wykonywany podczas wyświetlania DialogFragment jako okna dialogowego, ale kod onCreateView () można wywołać, gdy DialogFragment jest używany jako fragment w układzie.
// 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; }
źródło
Jeśli chcesz mieć łatwy dostęp do właściwości okna dialogowego, takich jak tytuł i przycisk odrzucenia, ale chcesz również użyć własnego układu, możesz użyć LayoutInflator w swoim Konstruktorze, gdy zastępujesz 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(); }
źródło