findViewById () लेआउट XML में कस्टम घटक के लिए शून्य देता है, अन्य घटकों के लिए नहीं


91

मेरे पास res/layout/main.xmlइन तत्वों और अन्य शामिल हैं:

<some.package.MyCustomView android:id="@+id/foo" (some other params) />
<TextView android:id="@+id/boring" (some other params) />

मेरी गतिविधि के कार्य में, मैं यह करता हूं:

setContentView(R.layout.main);
TextView boring = (TextView) findViewById(R.id.boring);
// ...find other elements...
MyCustomView foo = (MyCustomView) findViewById(R.id.foo);
if (foo == null) { Log.d(TAG, "epic fail"); }

अन्य तत्व सफलतापूर्वक पाए जाते हैं, लेकिन fooवापस शून्य आता है। MyCustomView में एक कंस्ट्रक्टर है MyCustomView(Context c, AttributeSet a)और Log.d(...)उस कंस्ट्रक्टर के अंत में "महाकाव्य विफल" से ठीक पहले लॉगकैट में सफलतापूर्वक दिखाई देता है।

fooअशक्त क्यों है ?

जवाबों:


182

क्योंकि कंस्ट्रक्टर में मेरे super(context)बजाय था super(context, attrs)

समझ में आता है, यदि आप आईडी जैसी विशेषताओं में पास नहीं होते हैं, तो दृश्य में कोई आईडी नहीं होगी और इसलिए इस आईडी का उपयोग करने योग्य नहीं होगा। :-)


1
हमेशा अपने सवालों के जवाब देने में सक्षम होना अच्छा लगता है :) स्वीकार किए गए उत्तर के रूप में भी आपको चिह्नित करना सुनिश्चित करें।
मैट एमएससी

वास्तव में। ऐसा तब करेगा जब SO मुझे अनुमति देगा ("आप 2 दिनों में अपना उत्तर स्वयं स्वीकार कर सकते हैं।")
क्रिस बॉयल

4
भी, तुम लाइनों की तरह नहीं होना (MyCustomView) foo = findViewById(R.id.foo);चाहिए MyCustomView foo = (MyCustomView) findViewById(R.id.foo);?
जेरेमी लोगान

3
एक ही समस्या थी, मेरे मामले में मैं setContentView () को भूल गया था .. XD
टॉम ब्रिटो

Vogella.com पर ऐसी बातें करने के लिए एक अच्छा उदाहरण है: vogella.com/articles/AndroidCustomViews/article.html
Wolkenjaeger

27

मेरे पास एक ही समस्या है क्योंकि मेरे कस्टम व्यू में मैंने कंस्ट्रक्टर को ओवरराइड किया था, लेकिन सुपर कॉन्ट्रैक्टर थॉट अटॉर्म्स पैरामीट को आमंत्रित किया था। वह कॉपी पेस्ट है)

मेरा पिछला रचनाकार संस्करण:

    public TabsAndFilterRelativeLayout(Context context, AttributeSet attrs) {
            super(context);
}

अब मेरे पास है:

    public TabsAndFilterRelativeLayout(Context context, AttributeSet attrs) {
            super(context, attrs);}

और वह काम करता है!


एक ही मुद्दा यहाँ। संयोग से यह मेरे लिए भी एक कॉपी पेस्ट त्रुटि थी।
कर्टकोबैन

वही चीज़ मेरे साथ हुई। Stackoverflow पर सबसे सही जवाब। जब एट्रीब्यूट को वापस जोड़ते हैं, तो सब कुछ ठीक है।
स्पाइकयांग

मुझे लगता है कि हम सभी को कस्टम दृश्य के साथ एक ही ट्यूटोरियल देखा;) इस त्रुटि ने मुझे व्यर्थ डिबगिंग का 0,5h लिया ...
क्राव्वेकिफिर

यह मेरे लिए भी काम किया! मैंने काफी समय तक इससे बल्लेबाजी की। धन्यवाद!
us_david

18

मुझे भी यही समस्या थी। मेरी गलती यह थी कि: मैंने लिखा था

        LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View layout=inflater.inflate(R.layout.dlg_show_info, null);
        alertDlgShowInfo.setView(layout);
        TableRow trowDesc=(TableRow)findViewById(R.id.trowDesc);

और जैसा कि मैंने एक एक्सएमएल फ़ाइल से दृश्य को "लोड" करने के लिए एक फ्लोटर का उपयोग किया था, अंतिम पंक्ति गलत थी। इसे हल करने के लिए, मुझे लिखना था:

TableRow trowDesc=(TableRow)layout.findViewById(R.id.trowDesc);

मैंने अपना समाधान लिखा है, यदि किसी को वही समस्या है।


यार, तुम एक जीनियस हो। यही एकमात्र समाधान था जो मेरे लिए SO पर पढ़े गए सभी लोगों के लिए काम करता था
इगोरगानोपल्स्की

मेरे लिए भी यही समस्या थी। वाह, क्या एक टुकड़ा ... मुझे अपने दम पर यह पता लगाने के लिए दिन लगेंगे। धन्यवाद!
सकारात्मक

18

लगता है कि कारणों की एक किस्म है। मैंने बस इसी तरह की समस्या को हल करने के लिए ग्रहण में "क्लीन ..." का इस्तेमाल किया। (FindViewByID ने किसी कारण से पहले काम किया था और अशक्त होने लगा था।)


1
जाहिर है, अंतर्निहित समस्या यह है कि R.java ID किसी तरह टूट जाती है या शायद अपडेट नहीं होती है। मैंने इसे केवल आईडी के साथ ही नहीं, बल्कि अन्य मामलों में भी देखा है, जैसे कि TextView आदि में प्रदर्शित गलत स्ट्रिंग वास्तव में नहीं जानते कि ऐसा क्यों होता है, हालांकि।
जेलिफ़िश

यह मुझे बहुत लंबे समय तक दु: ख दे रहा था - एक साफ वास्तव में मेरे लिए इसे ठीक कर दिया।
निकोलस एमटी इलियट

1
क्लीनअप, वास्तव में। वाह, कि बेकार है!
टिम बुथ

11

एक ही मुद्दा है, लेकिन अलग समाधान: मैंने फोन नहीं किया

setContentView(R.layout.main)

पहले जैसा मैंने यहां बताया गया दृश्य देखने की कोशिश की


मुझे लगता है कि यह समाधान है यदि आपको वर्तमान संबंधित दृश्य के बजाय अन्य दृश्य पर एक तत्व मिल रहा है।
स्टारकाब

4

यदि आपके पास कई लेआउट संस्करण हैं (स्क्रीन घनत्व के आधार पर, एसडीके संस्करण) यह सुनिश्चित करें कि उन सभी में वह तत्व शामिल है जिसे आप खोज रहे हैं।


2

मेरे मामले में findViewById अशक्त लौट रहा था क्योंकि मेरा कस्टम दृश्य मुख्य XML में कुछ इस तरह दिखता था:

        <com.gerfmarquez.seekbar.VerticalSeekBar  
            android:id="@+id/verticalSeekBar"
            android:layout_width="wrap_content" 
            android:layout_height="fill_parent" 
            />

और मुझे पता चला कि जब मैंने xmlns सामान जोड़ा तो यह इस तरह काम किया:

        <com.gerfmarquez.seekbar.VerticalSeekBar  
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/verticalSeekBar"
            android:layout_width="wrap_content" 
            android:layout_height="fill_parent" 
            />


1

मेरे लिए, प्रॉब्लम तब हल की गई थी जब मैंने प्रोजेक्ट सेटिंग्स में जावा बिल्ड पाथ में रिस फोल्डर को सोर्स में जोड़ा था।


1

मैं थोड़ी देर पहले उसी मुद्दे पर भाग गया जब मैंने लेआउट XML के माध्यम से एक कस्टम दृश्य जोड़ा और फिर आवेदन में कहीं और कॉलबैक संलग्न करने की कोशिश की ...

मैंने एक कस्टम दृश्य बनाया और इसे मेरे "layout_main.xml" में जोड़ा

public class MUIComponent extends SurfaceView implements SurfaceHolder.Callback {
    public MUIComponent (Context context, AttributeSet attrs ) {
        super ( context, attrs );
    }
    // ..
}

और मुख्य गतिविधि में मैं कुछ कॉलबैक संलग्न करना चाहता था और एक्सएम से यूआई तत्वों के संदर्भ प्राप्त करना चाहता था।

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // ...

        MUIInitializer muiInit = new MUIInitializer();
        muiInit.setupCallbacks(this);
        muiInit.intializeFields(this);
    }       
}

Initilizer कुछ भी फैंसी नहीं कर रहा था, लेकिन कस्टम दृश्य (MUIComponent) या अन्य गैर-कस्टम UI तत्वों को बनाने के लिए किए गए किसी भी परिवर्तन बस आवेदन में दिखाई नहीं दे रहे थे।

public class MUIInitializer {

    // ...

    public void setupCallbacks ( Activity mainAct ) {


        // This does NOT work properly
        // - The object instance returned is technically an instance of my "MUICompnent" view
        //   but it is a *different* instance than the instance created and shown in the UI screen
        // - Callbacks never get triggered, changes don't appear on UI, etc.
        MUIComponent badInst = (MUIComponent) mainAct.findViewById(R.id.MUIComponent_TESTSURF);


        // ...
        // This works properly

        LayoutInflater inflater = (LayoutInflater) mainAct.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View inflatedLayout = inflater.inflate ( R.layout.activity_main, null );

        MUIComponent goodInst = (MUIComponent) inflatedLayout.findViewById(R.id.MUIComponent_TESTSURF);


        // Add callbacks
        // ...
    }

}

"BadInst" और "goodInst" के बीच का अंतर है:

  • badInst गतिविधि के findViewByID का उपयोग करता है
  • goodInst लेआउट को फुलाता है और लुकअप करने के लिए फुले हुए लेआउट का उपयोग करता है

नोट किए गए विंसेंट के पास एक ही समाधान है ... और उसका उत्तर छोटा है ... +1 उसके बजाय :)
DevByStarlight

1

वियर के लिए कस्टम घटक के साथ मेरे साथ ऐसा हुआ, लेकिन यह सलाह का एक सामान्य टुकड़ा है। यदि आप एक स्टब का उपयोग कर रहे हैं (जैसे मैं उपयोग कर रहा था WatchViewStub), तो आप कॉल को findViewById()कहीं भी नहीं रख सकते । स्टब के अंदर सब कुछ पहले फुलाया जाना चाहिए, जो अभी नहीं होता है setContentView()। इस प्रकार, आपको कुछ इस तरह से लिखना चाहिए ताकि यह हो सके कि प्रतीक्षा करें:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_wear);
    final WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
    stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
        @Override
        public void onLayoutInflated(WatchViewStub stub) {
            myCustomViewInst = (MyCustomView) findViewById(R.id.my_custom_view);
            ...

0

मेरी समस्या एक टाइपो थी। मैंने android.idइसके बजाय (डॉट) लिखा था android:id। : पी

जाहिरा तौर पर मेरे कस्टम घटक xml के भीतर कोई वाक्यविन्यास जाँच नहीं है। :(


0

एक ही समस्या थी।

मेरे पास कुछ बच्चों के साथ लेआउट था। उनमें से एक के निर्माण से मैं दूसरे बच्चे को संदर्भ (reference.findViewById का उपयोग करके) प्राप्त करने की कोशिश कर रहा था। यह काम नहीं कर रहा था क्योंकि दूसरे बच्चे को लेआउट में आगे परिभाषित किया गया था।

मैंने इसे इस तरह हल किया है:

setContentView(R.layout.main);
MyView first = findViewById(R.layout.first_child);
first.setSecondView(findViewById(R.layout.second_child));

यह बच्चों के आदेश के विपरीत होने पर भी काम करेगा, लेकिन मुझे लगता है कि इसे आम तौर पर ऊपर की तरह किया जाना चाहिए।


1
सामान्य तौर पर आपको findViewByIdएक के कंस्ट्रक्टर में उपयोग नहीं करना चाहिए View, बल्कि प्रारंभिक कोड डाल देना चाहिए OnFinishInflate?
संजय मनोहर

0

findViewById()विधि कभी कभी रिटर्न nullजब लेआउट की जड़ नहीं है android:idविशेषता। लेआउट xml फ़ाइल बनाने के लिए एक्लिप्स विज़ार्ड स्वचालित रूप android:idसे रूट तत्व के लिए विशेषता उत्पन्न नहीं करता है।


0

मेरे मामले में दृश्य माता-पिता में था, उस दृश्य में नहीं जिसे मैं इसे कॉल करने का प्रयास कर रहा था। इसलिए बच्चे के दृश्य में मुझे कॉल करना पड़ा:

RelativeLayout relLayout = (RelativeLayout) this.getParent();
View view1 = relLayout.findViewById(R.id.id_relative_layout_search);

0

'स्वच्छ' विकल्प ने मेरे लिए काम किया।

मेरे मामले में, मूल कारण यह है कि स्रोत कोड एक नेटवर्क शेयर पर रहता है, और मेरे वर्कस्टेशन और फाइलसेवर को सही ढंग से सिंक्रनाइज़ नहीं किया गया था, और 5 सेकंड तक सूख गया था। एक्लिप्स द्वारा बनाई गई फाइलों पर टाइमस्टैम्प्स अतीत में हैं (क्योंकि वे फाइलसेवर द्वारा असाइन किए गए हैं) वर्कस्टेशन की घड़ी को wrt करते हैं, जिससे एक्लिप्स उत्पन्न और स्रोत फ़ाइलों के बीच निर्भरता को गलत तरीके से हल कर सकते हैं। इस मामले में, एक 'क्लीन' काम करता दिखाई देता है, क्योंकि यह एक वृद्धिशील बिल्ड के बजाय एक पूर्ण पुनर्निर्माण को मजबूर करता है जो गलत टाइमस्टैम्प पर निर्भर करता है।

एक बार जब मैंने अपने कार्य केंद्र पर एनटीपी सेटिंग्स तय कर ली, तो समस्या फिर कभी नहीं हुई। उचित एनटीपी सेटिंग्स के बिना, यह हर कुछ घंटों में होता है, क्योंकि घड़ियां तेजी से बहती हैं।


ऊपर के उत्तर की टिप्पणी के लिए इसे जोड़ना चाहिए
ट्रिंग गुयेन

0

बाहर देखने के लिए उत्तरों में एक और तुच्छ गलती जोड़ने के लिए:

जांचें कि आप वास्तव में सही लेआउट XML फ़ाइल का संपादन कर रहे हैं ...


0

मैं एक ही समस्या थी क्योंकि मैं अपने सभी लेआउट फ़ोल्डरों में व्यू आईडी को अपडेट करना भूल गया था।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.