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


81

내 레이아웃을 사용하여 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

난 당황해.


너무 늦기하지만 여전히 포스팅 비슷한 : stackoverflow.com/questions/21258228/...
래 가브 샤르마

답변:


37

이 첫 번째 접근 방식은 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();

1
이것은 실제로 작동합니다. 감사! 그래도 OnCreateView가 충돌하는 이유가 궁금합니다.
gghuffer

2
@gghuffer 4 개월이 늦었지만이 예외가 위의 코드에 의해 직접 발생했다고 생각하지 않습니다. 사람들이 콘텐츠를 추가 한 후 (예 : Exception 메시지가 이미 언급 한 requestFeature(...)것과 같은 requestWindowFeature(Window.FEATURE_NO_TITLE);) 호출하는 것이 더 일반적입니다 .
Griddo 2013 년

54

다음 코드에서 동일한 예외가 발생했습니다.

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 코멘트를 확인하십시오. 그가 말했듯이 실제로 둘 다 재정의 할 수 있지만 대화보기를 이미 만든 후보기를 확장하려고하면 문제가 발생합니다.


32
그것은 전적으로 사실이 아닙니다. 둘 다 재정의 할 수 있습니다 (실제로 DialogFragment가 그렇게 말합니다). 대화보기를 이미 만든 후보기를 확장하려고 할 때 문제가 발생합니다. 예외를 발생시키지 않고 savedInstanceState를 사용하는 등 onCreateView에서 다른 작업을 수행 할 수 있습니다.
Travis Christian

3
여기도 마찬가지입니다. 둘 다 지원해야합니다. 이것이 바로 조각을 인라인으로 사용하거나 대화 상자로 사용하는 아이디어입니다. 나에게 버그처럼 보입니다. 내가 할 수있는 최선의 방법은 대화 상자의 제목을 설정하는 것이지만 super를 호출하고 반환 된 대화 개체에 제목을 설정하여 onCreateDialog에 취소 버튼을 추가하는 것은 운이 좋지 않습니다. final Dialog dialog = super.onCreateDialog (savedInstanceState); dialog.setTitle (m_callback.getTitle ()); // 취소 버튼을 추가하면 운이 없습니다. return dialog;
farid_z

33

아래 코드는 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;
    }
}

1
당신은 링크가 있습니까?
Daniel Gomez Rico

@Zebphyr이 CustomDialogFragment를 내 활동에 대한 대화 상자로 사용하고 싶지만 위의 코드에는 onCreateDialog()메서드 에 R.layout.my_layout에 대한 언급이 없습니다 . 윌 onCreateView()이 경우에 도움이 될 것입니다?
CopsOnRoad

@Jack Jan, 예, onCreateView () 호출에서 레이아웃 파일을 지정할 수 있습니다.
Zephyr

16

다음은 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();


    }

1
이 예제는 완벽하게 작동합니다. 모든 코드를 onCreateView가 아닌 ​​onCreateDialog에 넣어야합니다. 이 코드를 통해 사용자는 버튼을 얻을 수있을뿐만 아니라이를 수행 할 수 있습니다. 완전한!
Brandon

10

@Xavier Egea가 말했듯이 onCreateView ()와 onCreateDialog ()가 모두 구현 된 경우 "콘텐츠를 추가하기 전에 requestFeature ()를 호출해야합니다"충돌이 발생할 위험이 있습니다. 이는 해당 조각을 대화 상자로 표시 () 할 때 onCreateDialog ()와 onCreateView ()가 모두 호출되기 때문입니다 (왜, 모르겠습니다). Travis Christian이 언급했듯이 onCreateDialog ()에서 대화 상자가 생성 된 후 onCreateView ()의 inflate ()가 충돌의 원인입니다.

이 두 함수를 모두 구현하지만이 충돌을 피하는 한 가지 방법 : getShowsDialog ()를 사용하여 onCreateView () 실행을 제한합니다 (따라서 inflate ()가 호출되지 않음). 이렇게하면 DialogFragment를 대화 상자로 표시 할 때 onCreateDialog () 코드 만 실행되지만 DialogFragment가 레이아웃에서 조각으로 사용될 때 onCreateView () 코드를 호출 할 수 있습니다.

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

onCreateView가 뷰를 구성하고 있기 때문에이 작업의 요점을 알 수 없습니다. onCreateView를 일반적인 팽창 코드로 유지할 수있는 두 위치 모두에서 뷰를 구성하려는 이유는 무엇이며 대화 상자에서 부풀려 질 것입니다
user1530779

@ user1530779 버튼은 어떻습니까? OnCreateDialog에서 빌더를 사용하여 버튼을 설정할 수 있으며 대화 상자에서 뷰가 부 풀릴 때 버튼을 가져 오기 위해 OnCreateView에서 무엇을해야합니까?
Varvara Kalinina

흠, Builder를 사용하면 예외가 발생하는 것 같습니다. 그렇다면 대화 상자에서 뷰가 부풀려지고 조각 일 때 버튼을 설정하지 않으면 버튼을 설정하는 방법은 무엇입니까?
Varvara Kalinina

글쎄, 당신이 대신 dialog.setContentView의 dialog.setView를 호출하는 경우이 방법을 사용하면 작성기 및 설정 버튼을 사용하여 대화 상자를 만들 경우에도 잘 작동 밝혀
Varvara 칼리 니나

6

제목 및 닫기 버튼과 같은 대화 상자 속성에 쉽게 액세스하고 싶지만 자체 레이아웃도 사용하려는 경우 onCreateDialog를 재정의 할 때 Builder와 함께 LayoutInflator를 사용할 수 있습니다.

@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();
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.