web-dev-qa-db-fra.com

Disposition personnalisée pour DialogFragment OnCreateView vs OnCreateDialog

J'essaie de créer un DialogFragment en utilisant ma propre mise en page.

J'ai vu plusieurs approches différentes. Parfois, la mise en page est définie dans OnCreateDialog comme ceci: (J'utilise Mono mais je me suis un peu 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 recherche sur Google, j’ai essayé la deuxième approche, qui consiste à remplacer OnCreateView

J'ai donc 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 perplexe.

74
gghuffer

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

Je suppose que vous ne parcourez pas la fonction findViewById() de 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();
35
Sam

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 remplacer n seul de onCreateView ou onCreateDialog dans un DialogFragment. Remplacer les deux entraînera une exception: "requestFeature () doit être appelé avant d'ajouter du contenu".

Important

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

53
Xavier Egea

Le code ci-dessous provient du guide Google. La réponse est que vous ne pouvez pas faire comme le vôtre dans onCreateDialog (), vous devez utiliser super.onCreateDialog () pour obtenir une boîte de dialogue.

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

Voici un exemple d'utilisation de findViewById dans un fragment de dialogue

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


    }
16
I'm_With_Stupid

Comme @Xavier Egea le dit, si onCreateView () et onCreateDialog () sont tous deux implémentés, vous courez le risque d'obtenir le "requestFeature () doit être appelé avant d'ajouter du contenu" crash. En effet, onCreateDialog () puis onCreateView () sont appelés lorsque vous affichez () ce fragment sous forme de dialogue (pourquoi, je ne sais pas). Comme Travis Christian l'a mentionné, la fonction inflate () dans onCreateView () après la création d'un dialogue dans onCreateDialog () est à l'origine du blocage.

Une façon d'implémenter ces deux fonctions, mais évitez cet incident: utilisez getShowsDialog () pour limiter l'exécution de votre onCreateView () (votre inflate () n'est donc pas appelée). Ainsi, seul votre code onCreateDialog () est exécuté lorsque vous affichez votre DialogFragment en tant que boîte de dialogue, mais votre code onCreateView () peut être appelé lorsque votre DialogFragment est utilisé en tant que fragment dans une présentation.

// 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;
}
10
Steve B

Si vous souhaitez accéder facilement aux propriétés de la boîte de dialogue, telles que le titre et le bouton de renvoi, mais que vous souhaitez également utiliser votre propre présentation, vous pouvez utiliser 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.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();
}
5
Jason Hartley