Пользовательский макет для DialogFragment OnCreateView и OnCreateDialog



Я пытаюсь создать 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.
поэтому после небольшого поиска в Google я попробовал второй подход, который включает переопределение 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


Я в тупике.

459   6  

6 ответов:

Это первый подход работает для меня... пока я не хочу использовать FindViewByID.

Я бы предположил, что вы не рассматриваете 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 (), вы должны использовать супер.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();
}

Comments

    Ничего не найдено.