programing

DialogFragment OnCreateView 대 OnCreateDialog의 사용자 지정 레이아웃

nasanasas 2020. 10. 21. 08:09
반응형

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

난 당황해.


이 첫 번째 접근 방식은 FindViewByID를 사용하고 싶을 때까지 저에게 효과적입니다.

에서 findViewById()반환 한 View로 범위 지정하지 않았다고 생각합니다 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;    
    }
}

DialogFragment에서 onCreateView 또는 onCreateDialog 중 하나만 재정의하도록 선택해야합니다 . 둘 다 재정의하면 "콘텐츠를 추가하기 전에 requestFeature ()를 호출해야합니다"라는 예외가 발생합니다.

중대한

완전한 답변은 @TravisChristian 코멘트를 확인하십시오. 그가 말했듯이 실제로 둘 다 재정의 할 수 있지만 대화 뷰를 이미 만든 후 뷰를 확장하려고하면 문제가 발생합니다.


아래 코드는 Google 가이드에서 가져온 것이므로 대답은 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;
    }
}

다음은 Dialog Fragment에서 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();


    }

As @Xavier Egea says, if you have both onCreateView() and onCreateDialog() implemented, you run the risk of getting the "requestFeature() must be called before adding content" crash. This is because BOTH onCreateDialog() then onCreateView() are called when you show() that fragment as a dialog (why, I don't know). As Travis Christian mentioned, the inflate() in onCreateView() after a dialog was created in onCreateDialog() is what causes the crash.

One way to implement both these functions, but avoid this crash: use getShowsDialog() to limit execution of your onCreateView() (so your inflate() is not called). This way only your onCreateDialog() code is executed when you are displaying your DialogFragment as a dialog, but your onCreateView() code can be called when your DialogFragment is being used as a fragment in a layout.

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

If you want to have easy access the dialog properties, like the title and the dismiss button, but you also want to use your own layout, you can use a LayoutInflator with your Builder when you override 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();
}

참고URL : https://stackoverflow.com/questions/13257038/custom-layout-for-dialogfragment-oncreateview-vs-oncreatedialog

반응형