एंड्रॉइड - एक कस्टम (मिश्रित) घटक लिखना


132

वर्तमान में मैं जो एंड्रॉइड ऐप विकसित कर रहा हूं उसमें एक मुख्य गतिविधि है जो काफी बड़ी हो गई है। यह मुख्य रूप से है क्योंकि इसमें TabWidget3 टैब होते हैं। प्रत्येक टैब में कुछ घटक होते हैं। गतिविधि को एक बार में उन सभी घटकों को नियंत्रित करना है। इसलिए मुझे लगता है कि आप सोच सकते हैं कि इस गतिविधि में 20 फ़ील्ड (लगभग हर घटक के लिए एक फ़ील्ड) पसंद हैं। इसके अलावा इसमें बहुत सारे तर्क हैं (श्रोता पर क्लिक करें, सूची भरने के लिए तर्क आदि)।

मैं घटक आधारित रूपरेखा में सामान्य रूप से क्या करता हूं, सब कुछ को कस्टम घटकों में विभाजित करना है। प्रत्येक कस्टम घटक के बाद एक स्पष्ट जिम्मेदारी होगी। इसमें सम्‍मिलित घटकों का समूह और उस घटक से संबंधित अन्य सभी तर्क शामिल होंगे।

मैंने यह पता लगाने की कोशिश की कि यह कैसे किया जा सकता है, और मुझे एंड्रॉइड डॉक्यूमेंटेशन में कुछ मिला जो उन्हें "कंपाउंड कंट्रोल" कहलाना पसंद है। (देखें http://developer.android.com/guide/topics/ui/custom-compenders.html#compound और "Compound Controls" अनुभाग पर स्क्रॉल करें) मैं एक XML फ़ाइल को परिभाषित करने वाली XML फ़ाइल के आधार पर इस तरह का एक घटक बनाना चाहूंगा। संरचना देखें।

प्रलेखन में यह कहता है:

ध्यान दें कि किसी गतिविधि के साथ की तरह, आप निहित घटकों को बनाने के लिए या तो घोषणात्मक (XML- आधारित) दृष्टिकोण का उपयोग कर सकते हैं, या आप उन्हें अपने कोड से प्रोग्रामेटिकली घोंसला बना सकते हैं।

खैर, यह अच्छी खबर है! एक्सएमएल-आधारित दृष्टिकोण बिल्कुल वही है जो मैं चाहता हूं! लेकिन यह नहीं कहता कि यह कैसे करना है, सिवाय इसके कि यह "एक गतिविधि के साथ की तरह है" ... लेकिन मैं एक गतिविधि में क्या करता हूं setContentView(...)एक्सएमएल से विचारों को फुलाया जाता है। यदि आप उपवर्ग उदाहरण के लिए वह विधि उपलब्ध नहीं है LinearLayout

तो मैंने इस तरह से XML को मैन्युअल रूप से बढ़ाने की कोशिश की:

public class MyCompoundComponent extends LinearLayout {

    public MyCompoundComponent(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(R.layout.my_layout, this);
    }
}

यह इस तथ्य को छोड़कर काम करता है कि एक्सएमएल मैं लोड कर रहा हूं LinearLayoutरूट रूट घोषित किया गया है। यह फुलाया LinearLayoutजा रहा है MyCompoundComponentजिसके परिणामस्वरूप एक बच्चा पहले से ही एक है LinearLayout!! तो अब हमारे बीच एक निरर्थक LinearLayout है MyCompoundComponentऔर इसके विचारों की वास्तव में आवश्यकता है।

क्या कोई मुझे इस बारे में बताने का एक बेहतर तरीका प्रदान कर सकता है, निरर्थक LinearLayoutतात्कालिकता से बचने के लिए ?


14
मुझे उन सवालों से प्यार है, जिनसे मैं कुछ सीखता हूं। धन्यवाद।
जेरेमी लोगान

5
मैंने हाल ही में इस बारे में एक ब्लॉग प्रविष्टि लिखी है: blog.jteam.nl/2009/10/08/exploring-the-world-of-android-part-3
टॉम वैन ज़ुमरेन

जवाबों:


101

अपने XML रूट के रूप में मर्ज टैग का उपयोग करें

<merge xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Your Layout -->
</merge>

इस लेख की जाँच करें।


10
आपका बहुत बहुत धन्यवाद! यह वहीं है जिसे मैं ढूंढ रहा था। कमाल है कि इतने लंबे सवाल का इतना कम जवाब कैसे हो सकता है। अति उत्कृष्ट!
टॉम वैन ज़ुमेरेन

परिदृश्य में इस मर्ज लेआउट को दर्शाने के बारे में क्या?
कोस्टाडिन

2
@ टिम्मम हाहाहा मैंने इस सवाल को बहुत पहले ही विजुअल एडिटर के अस्तित्व में आने से पहले पूछ लिया :)
टॉम वैन ज़ुमरेन

0

मुझे लगता है कि जिस तरह से आप इसे करने वाले हैं, वह XML रूट एलिमेंट के रूप में आपके क्लास के नाम का उपयोग करता है:

<com.example.views.MyView xmlns:....
       android:orientation="vertical" etc.>
    <TextView android:id="@+id/text" ... />
</com.example.views.MyView>

और फिर अपनी कक्षा को जो भी लेआउट आप उपयोग करना चाहते हैं से प्राप्त किया है। ध्यान दें कि यदि आप इस पद्धति का उपयोग कर रहे हैं तो आप यहां लेआउट इनफ्लोटर का उपयोग नहीं करते हैं।

public class MyView extends LinearLayout
{
    public ConversationListItem(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }
    public ConversationListItem(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
    }


    public void setData(String text)
    {
        mTextView.setText(text);
    }

    private TextView mTextView;

    @Override
    protected void onFinishInflate()
    {
        super.onFinishInflate();

        mTextView = (TextView)findViewById(R.id.text);
    }
}

और फिर आप सामान्य रूप में XML लेआउट में अपने दृश्य का उपयोग कर सकते हैं। यदि आप दृश्य को प्रोग्रामेटिक रूप से बनाना चाहते हैं तो आपको इसे स्वयं बढ़ाना होगा:

MyView v = (MyView)inflater.inflate(R.layout.my_view, parent, false);

दुर्भाग्य से यह आपको ऐसा करने की अनुमति नहीं देता है v = new MyView(context)क्योंकि नेस्टेड लेआउट समस्या के आसपास कोई रास्ता नहीं दिखता है, इसलिए यह वास्तव में पूर्ण समाधान नहीं है। आप MyViewइसे थोड़ा अच्छा बनाने के लिए इस तरह से एक विधि जोड़ सकते हैं :

public static MyView create(Context context)
{
    return (MyView)LayoutInflater.fromContext(context).inflate(R.layout.my_view, null, false);
}

डिस्क्लेमर: मैं पूर्ण बोलचाल पर बात कर सकता हूं।


धन्यवाद! मुझे लगता है कि यह उत्तर भी सही है :) लेकिन तीन साल पहले, जब मैंने यह सवाल पूछा था, तो "मर्ज" भी किया गया था!
टॉम वैन ज़ुमरेन

8
और फिर किसी के साथ और बस के साथ एक लेआउट कहीं में अपने कस्टम दृश्य का उपयोग करने के लिए आता की कोशिश करता <com.example.views.MyView />है और अपने setDataऔर onFinishInflateकॉल NPEs फेंकने शुरू, और आप पता नहीं क्यों है।
क्रिस्टोफर पेरी

यहां ट्रिक आपके कस्टम व्यू का उपयोग करने के लिए है, फिर कंस्ट्रक्टर में, एक लेआउट को फुलाने के लिए जो रूट के रूप में मर्ज टैग का उपयोग करता है। अब आप इसे XML में उपयोग कर सकते हैं, या बस इसे नया करके। सभी आधारों को कवर किया गया है, जो कि वास्तव में प्रश्न / स्वीकृत उत्तर एक साथ है। हालाँकि आप जो नहीं कर सकते हैं वह सीधे लेआउट के लिए है। यह अब कस्टम नियंत्रण द्वारा 'स्वामित्व' है और इसका उपयोग केवल निर्माता द्वारा किया जाना चाहिए। लेकिन अगर आप इस दृष्टिकोण का उपयोग कर रहे हैं, तो आपको इसे और कहीं भी उपयोग करने की आवश्यकता क्यों होगी? आप नहीं करेंगे।
मार्क ए। डोनोहे
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.