Disposition personnalisée pour DialogFragment OnCreateView et OnCreateDialog

J’essaie de créer un DialogFragment en utilisant ma propre disposition.

J’ai vu deux approches différentes. Parfois, la mise en page est définie dans OnCreateDialog comme ceci: (J’utilise Mono mais je me suis habitué à 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(); } 

Cette première approche fonctionne pour moi jusqu’à ce que je veuille utiliser findViewByID. donc après un peu de googler j’ai essayé la deuxième approche qui consiste à OnCreateView

Donc, j’ai commenté deux lignes de OnCreateDialog qui définissent la mise en page, puis ajouté ceci:

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

ce qui me donne une belle erreur:

 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 

Je suis déconcerté

Cette première approche fonctionne pour moi jusqu’à ce que je veuille utiliser FindViewByID.

Je suppose que vous findViewById() pas findViewById() sur la vue renvoyée par inflate() , essayez ceci:

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

J’ai eu la même exception avec le code suivant:

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

Vous devez choisir de ne remplacer qu’un seul onCreateView ou onCreateDialog dans un DialogFragment. La substitution des deux entraînera l’exception: “requestFeature () doit être appelé avant d’append du contenu”.

Important

Pour une réponse complète, consultez le commentaire @TravisChristian. Comme il l’a dit, vous pouvez remplacer les deux en effet, mais le problème vient lorsque vous essayez de gonfler la vue après avoir déjà créé la vue de dialog.

En dessous du code vient de Google Guide, donc la réponse est que vous ne pourriez pas faire comme le vôtre dans onCreateDialog (), vous devez utiliser super.onCreateDialog () pour obtenir une boîte de dialog.

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

Voici un exemple d’utilisation de findViewById dans un fragment de dialog

 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(bandSsortingng); builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { getDialog().dismiss(); } } ); return builder.create(); } 

Comme le dit @Xavier Egea, si on a implémenté onCreateView () et onCreateDialog (), vous risquez d’obtenir le crash de “requestFeature () doit être appelé avant d’append du contenu”. C’est parce que les deux onCreateDialog () puis onCreateView () sont appelés quand vous montrez () ce fragment comme un dialog (pourquoi, je ne sais pas). Comme l’a mentionné Travis Christian, le gonflage () dans onCreateView () après la création d’une boîte de dialog dans onCreateDialog () est la cause du plantage.

Une façon d’implémenter ces deux fonctions, mais évitez ce crash: utilisez getShowsDialog () pour limiter l’exécution de votre onCreateView () (donc votre inflate () n’est pas appelé). De cette façon, seul votre code onCreateDialog () est exécuté lorsque vous affichez votre DialogFragment en tant que boîte de dialog, mais votre code onCreateView () peut être appelé lorsque votre DialogFragment est utilisé comme fragment dans une mise en page.

 // 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; } 

Si vous souhaitez accéder facilement aux propriétés de la boîte de dialog, telles que le titre et le bouton de suppression, mais que vous souhaitez également utiliser votre propre mise en page, vous pouvez utiliser un LayoutInflator avec votre générateur lorsque vous substituez 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.ssortingng.enter, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // Clicked 'Okay' } }) .setNegativeButton(R.ssortingng.dismiss, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // Clicked 'Cancel' } }); return builder.create(); }