DialogFragment OnCreateView बनाम OnCreateDialog के लिए कस्टम लेआउट


81

मैं अपने स्वयं के लेआउट का उपयोग करके एक DialogFragment बनाने की कोशिश कर रहा हूं।

मैंने कुछ अलग दृष्टिकोण देखे हैं। कभी-कभी लेआउट इस तरह OnCreateDialog में सेट किया जाता है: (मैं मोनो का उपयोग कर रहा हूं, लेकिन मैंने जावा के लिए कुछ हद तक उपयोग किया है)

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()इस दृष्टिकोण से लौटे नहीं हैं 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 महीने की देरी है, मुझे नहीं लगता कि यह अपवाद सीधे ऊपर दिए गए कोड के कारण है। यह अधिक सामान्य है कि लोग सामग्री जोड़ने के बाद requestFeature(...)(या ऐसा कुछ requestWindowFeature(Window.FEATURE_NO_TITLE);) कॉल करते हैं (जैसे अपवाद संदेश पहले से ही बताता है)।
ग्रिद्दो

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

आपको केवल एक को ओवरराइड करना होगा डायलॉगफ्रेगमेंट में एक onCreateView या onCreateDialog । दोनों को ओवरराइड करने के परिणामस्वरूप अपवाद होगा: "requestFeature () को सामग्री जोड़ने से पहले बुलाया जाना चाहिए"।

जरूरी

पूर्ण उत्तर के लिए @TravisChristian टिप्पणी देखें। जैसा कि उन्होंने कहा, आप वास्तव में दोनों को ओवरराइड कर सकते हैं, लेकिन समस्या तब आती है जब आप पहले से ही संवाद दृश्य बनाने के बाद दृश्य को बढ़ाने की कोशिश करते हैं।


32
यह पूरी तरह सच नहीं है। आप दोनों को ओवरराइड कर सकते हैं (वास्तव में डायलॉगफ्रेगमेंट ऐसा कहता है), समस्या तब आती है जब आप पहले से ही डायलॉग व्यू बनाने के बाद व्यू को बढ़ाने की कोशिश करते हैं। आप अभी भी onCreateView में अन्य काम कर सकते हैं, जैसे बिना किसी अपवाद के, saveInstanceState का उपयोग करना।
ट्रैविस क्रिश्चियन

3
मुझे भी। दोनों का समर्थन करने की जरूरत है। यह या तो खंड इनलाइन का उपयोग करने या एक संवाद के रूप में विचार है। मेरे लिए एक बग की तरह लगता है। सबसे अच्छा मैं कर सकता था, डायलॉग के लिए शीर्षक सेट किया गया था, लेकिन लौटाए गए डायल ऑब्जेक्ट पर सुपर और सेटिंग शीर्षक को कॉल करके onCreateDialog में एक रद्द बटन जोड़ने का कोई सौभाग्य नहीं है: अंतिम डायलॉग डायलॉग = super.onCreateDialog (सहेजी गई सामग्री); Dial.setTitle (m_callback.getTitle ()); // कोई भाग्य नहीं है रद्द करें बटन वापसी संवाद;
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
क्या आपके पास एक लिंक है?
डैनियल गोमेज़ रिको

@Zebphyr अगर मैं इस CustomDialogFragment का उपयोग अपनी गतिविधि के लिए एक संवाद के रूप में करना चाहता हूं, लेकिन ऊपर दिए गए कोड में R.layout.my_layout का कोई उल्लेख नहीं है onCreateDialog()। विल onCreateView()इस मामले में मदद मिलेगी?
कोप्सऑनराड

@Jack Jan, Yes, आप लेआउट फ़ाइल को onCreateView () कॉल में निर्दिष्ट कर सकते हैं।
ज़ेफियर

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
यह उदाहरण मेरे लिए पूरी तरह से काम करता है। आपको अपने सभी कोड onCreateDialog के बजाय onCreateView में डालने होंगे। यह कोड उपयोगकर्ता को बटन के साथ ही ऐसा करने की अनुमति देता है। उत्तम!
ब्रैंडन

10

जैसा कि @Xavier Egea कहता है, अगर आपके पास onCreateView () और onCreateDialog () दोनों लागू हैं, तो आप "requestFeature () को सामग्री जोड़ने से पहले कॉल करने का जोखिम चलाते हैं" क्रैश। इसका कारण यह है कि दोनों onCreateDialog () तब onCreateView () कहलाते हैं जब आप एक डायलॉग (क्यों, मुझे नहीं पता) के रूप में दिखाते हैं। जैसा कि ट्रैविस क्रिश्चियन ने उल्लेख किया है, onCreateDialog () में एक डायलॉग बनाए जाने के बाद onCreateView () में इनफ्लो () दुर्घटना का कारण बनता है।

इन दोनों कार्यों को लागू करने का एक तरीका है, लेकिन इस दुर्घटना से बचें: getShowsDialog () का उपयोग करके अपने onCreateView () (ताकि आपका फुलाया () नहीं कहा जाता है) के निष्पादन को सीमित करें। इस तरह से केवल आपका onCreateDialog () कोड तब निष्पादित किया जाता है जब आप अपने DialogFragment को एक डायलॉग के रूप में प्रदर्शित कर रहे होते हैं, लेकिन जब आपका 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 बटन के बारे में क्या? OnCreateDialog में मैं बटन सेट करने के लिए बिल्डर का उपयोग कर सकता हूं और जब संवाद में दृश्य को फुलाया जाता है तो बटन प्राप्त करने के लिए मुझे OnCreateView में क्या करना चाहिए?
वरवारा कलिनािना 13

हम्म, ऐसा लगता है जैसे बिल्डर का उपयोग मुझे अपवाद देता है। तो बटन को सेटअप करने का क्या तरीका होगा यदि दृश्य संवाद में फुलाया जाता है और जब यह केवल एक टुकड़ा होता है तो कोई बटन सेट नहीं करता है?
वरवरा कलिनािना

खैर, यह पता चला है कि अगर आप dialog.setContentView के बजाय dialog.setView फोन इस दृष्टिकोण ठीक काम करता है, भले ही आप एक बिल्डर और सेट बटन के साथ अपने संवाद बनाने
Varvara कलिनिना

6

यदि आप शीर्षक और बर्खास्त बटन की तरह संवाद गुणों का आसान उपयोग करना चाहते हैं, लेकिन आप अपने स्वयं के लेआउट का उपयोग करना चाहते हैं, तो जब आप 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();
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.