XML का उपयोग करके एक कस्टम Android UI तत्व घोषित करना


472

मैं XML का उपयोग करके Android UI तत्व की घोषणा कैसे करूं?


15
अगर किसी को समर्थित, अंतर्निहित विशेषता प्रारूपों की सूची दिखती है, तो इसे यहां पाया जा सकता है
Marcin Orlowski

1
शुरू करने के लिए अच्छा ट्यूटोरियल -> एंड्रॉइड पर कंपाउंड व्यू बनाना
गायन वीरकुट्टी

जवाबों:


840

Android डेवलपर गाइड में बिल्डिंग कस्टम कंपोनेंट्स नामक एक सेक्शन है । दुर्भाग्य से, एक्सएमएल विशेषताओं की चर्चा केवल लेआउट फ़ाइल के अंदर नियंत्रण की घोषणा को कवर करती है और वास्तव में वर्ग आरंभीकरण के अंदर मूल्यों को संभालना नहीं है। कदम इस प्रकार हैं:

1. घोषणा विशेषताएँ values\attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyCustomView">
        <attr name="android:text"/>
        <attr name="android:textColor"/>            
        <attr name="extraInformation" format="string" />
    </declare-styleable>
</resources>

declare-styleableटैग में एक अयोग्य नाम के उपयोग पर ध्यान दें । गैर-मानक एंड्रॉइड विशेषताओं की तरह extraInformationउनके प्रकार को घोषित करने की आवश्यकता है। सुपरक्लास में घोषित किया गया टैग उप-वर्गों में उपलब्ध होगा बिना पुनर्वितरित किए।

2. कंस्ट्रक्टर बनाएं

चूंकि दो निर्माणकर्ता हैं जो AttributeSetआरंभीकरण के लिए उपयोग करते हैं , इसलिए निर्माणकर्ताओं को कॉल करने के लिए एक अलग प्रारंभिक विधि बनाना सुविधाजनक है।

private void init(AttributeSet attrs) { 
    TypedArray a=getContext().obtainStyledAttributes(
         attrs,
         R.styleable.MyCustomView);

    //Use a
    Log.i("test",a.getString(
         R.styleable.MyCustomView_android_text));
    Log.i("test",""+a.getColor(
         R.styleable.MyCustomView_android_textColor, Color.BLACK));
    Log.i("test",a.getString(
         R.styleable.MyCustomView_extraInformation));

    //Don't forget this
    a.recycle();
}

R.styleable.MyCustomViewएक ऑटोजेनरेटेड int[]संसाधन है जहां प्रत्येक तत्व एक विशेषता की आईडी है। एक्सएमएल में प्रत्येक गुण के लिए तत्व नाम के गुण को जोड़कर गुण उत्पन्न होते हैं। उदाहरण के लिए, R.styleable.MyCustomView_android_textइसमें android_textविशेषता है MyCustomView। विशेषताएँ तब TypedArrayविभिन्न getकार्यों का उपयोग करके पुनर्प्राप्त की जा सकती हैं । यदि एक्सएमएल में परिभाषित विशेषता को परिभाषित नहीं किया गया है, तो nullवापस कर दिया जाता है। सिवाय, ज़ाहिर है, अगर वापसी का प्रकार एक आदिम है, जिस स्थिति में दूसरा तर्क वापस आ गया है।

यदि आप सभी विशेषताओं को पुनर्प्राप्त नहीं करना चाहते हैं, तो इस सरणी को मैन्युअल रूप से बनाना संभव है। मानक एंड्रॉइड विशेषताओं के लिए आईडी इसमें शामिल हैं android.R.attr, जबकि इस परियोजना के लिए विशेषताओं में हैं R.attr

int attrsWanted[]=new int[]{android.R.attr.text, R.attr.textColor};

कृपया ध्यान दें कि आपको कुछ भी उपयोग नहीं करना चाहिए android.R.styleable, क्योंकि इस धागे के अनुसार यह भविष्य में बदल सकता है। यह अभी भी प्रलेखन में है क्योंकि एक ही स्थान पर इन सभी स्थिरांक को देखना उपयोगी है।

3. जैसे लेआउट फ़ाइलों में इसका उपयोग करें layout\main.xml

xmlns:app="http://schemas.android.com/apk/res-auto"शीर्ष स्तर xml तत्व में नाम स्थान की घोषणा शामिल करें । नामस्थान टकराव से बचने के लिए एक विधि प्रदान करते हैं जो कभी-कभी तब होती है जब विभिन्न स्कीमा एक ही तत्व नामों का उपयोग करते हैं ( इस जानकारी के लिए इस लेख को देखें )। URL केवल विशिष्ट पहचान स्कीमा का एक तरीका है - कुछ भी वास्तव में उस URL पर होस्ट करने की आवश्यकता नहीं है । यदि यह कुछ भी नहीं करता दिखाई देता है, तो यह इसलिए है क्योंकि आपको वास्तव में नामस्थान उपसर्ग को जोड़ने की आवश्यकता नहीं है जब तक कि आपको एक संघर्ष को हल करने की आवश्यकता न हो।

<com.mycompany.projectname.MyCustomView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@android:color/transparent"
    android:text="Test text"
    android:textColor="#FFFFFF"
    app:extraInformation="My extra information"
/> 

पूरी तरह से योग्य नाम का उपयोग करके कस्टम दृश्य का संदर्भ दें।

Android लेबल दृश्य नमूना

यदि आप एक पूर्ण उदाहरण चाहते हैं, तो Android लेबल दृश्य नमूना देखें।

LabelView.java

 TypedArray a=context.obtainStyledAttributes(attrs, R.styleable.LabelView);
 CharSequences=a.getString(R.styleable.LabelView_text);

attrs.xml

<declare-styleable name="LabelView">
    <attr name="text"format="string"/>
    <attr name="textColor"format="color"/>
    <attr name="textSize"format="dimension"/>
</declare-styleable>

custom_view_1.xml

<com.example.android.apis.view.LabelView
    android:background="@drawable/blue"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    app:text="Blue" app:textSize="20dp"/>

यह LinearLayoutएक नाम स्थान विशेषता के साथ निहित है :xmlns:app="http://schemas.android.com/apk/res-auto"

लिंक


14
मैं यह जोड़ना चाहूंगा कि यदि आपके रूट तत्व को आपके कस्टम नेमस्पेस की आवश्यकता है, तो आपको दोनों मानक एंड्रॉइड नेमस्पेस और अपने स्वयं के कस्टम एक को जोड़ना होगा अन्यथा आपको त्रुटियों का निर्माण करने का अनुभव हो सकता है।
चेस

11
यह उत्तर इंटरनेट पर कस्टम XML पार्म्स पर स्पष्ट संसाधन है जिसे मैं खोजने में सक्षम था। धन्यवाद, केसबश।
आर्टेम रसाकोवस्की

2
किसी कारण से, दृश्य संपादक Android: पाठ के लिए लिखित पाठ मान का उपयोग करने से इनकार करता है, फिर भी डिवाइस इसे ठीक उपयोग करता है। कैसे ?
Android डेवलपर

2
@androiddeveloper ऐसा लगता है कि ग्रहण संपादक सभी एंड्रॉइड के लिए मूल्यों का उपयोग करने से इनकार करता है: विशेषताएँ। मैं जानना चाहूंगा कि क्या यह एक सुविधा या बग है
deej

4
Xmlns का क्या उद्देश्य है: ऐप नेमस्पेस और रेस-ऑटो?
इगोरगानापोलस्की

91

महान संदर्भ। धन्यवाद! इसके अतिरिक्त:

यदि आपके पास एक लाइब्रेरी प्रोजेक्ट शामिल है, जो एक कस्टम दृश्य के लिए कस्टम विशेषताओं की घोषणा करता है, तो आपको अपने प्रोजेक्ट के नाम स्थान की घोषणा करनी होगी, न कि लाइब्रेरी की। उदाहरण के लिए:

यह देखते हुए कि लाइब्रेरी में पैकेज "com.example.library.customview" है और वर्किंग प्रोजेक्ट में पैकेज "com.example.customview" है, तब:

काम नहीं करेगा (त्रुटि दिखाता है "त्रुटि: पैकेज 'com.example.library.customview' में विशेषता 'newAttr' के लिए कोई संसाधन पहचानकर्ता नहीं मिला है):

<com.library.CustomView
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res/com.example.library.customview"
        android:id="@+id/myView"
        app:newAttr="value" />

काम करेगा:

<com.library.CustomView
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res/com.example.customview"
        android:id="@+id/myView"
        app:newAttr="value" />

47
यह ADT 17 पूर्वावलोकन में ~ तय किया गया है। पुस्तकालय से ऐप के नाम स्थान का उपयोग करने के लिए, xmlns:app="http://schemas.android.com/apk/res-auto"टिप्पणी 57 देखें कोड में देखें।
Googlep

2
अपने कस्टम नेमस्पेस को शामिल करना अब एक त्रुटि हैSuspicious namespace: Did you mean http://schemas.android.com/apk/res-auto
बेन विल्किंसन

कस्टम नेमस्पेस रेस-ऑटो में समाप्त होता है क्योंकि हम एंड्रॉइड स्टूडियो और ग्रैडल का उपयोग कर रहे हैं। अन्यथा (जैसे कुछ ग्रहण संस्करण) यह आम तौर पर देयता में समाप्त होगा / [आपका पैकेज नाम]
ब्रह्मांड

कस्टम नेमस्पेस समाप्त होता है res-autoक्योंकि हम एंड्रॉइड स्टूडियो और ग्रैडल का उपयोग कर रहे हैं। अन्यथा (जैसे कुछ ग्रहण संस्करण) यह आमतौर पर समाप्त हो जाएगा lib/[your package name]। अर्थातhttp://schemas.android.com/apk/lib/[your package name]
ब्रह्मांड

27

सबसे अधिक वोट किए गए उत्तर के अलावा।

obtainStyledAttributes ()

जब हम एंड्रॉइड का उपयोग करके कस्टम दृश्य बनाते हैं, तो मैं कुछ शब्दों को जोड़ना चाहता हूं। खासकर जब हम TextAppearance का उपयोग करते हैं।
जैसा कि "2. निर्माण करने वाले" में उल्लेख किया गया था, कस्टम दृश्य को इसके निर्माण पर एट्रीब्यूटसेट मिलता है। मुख्य उपयोग हम TextView स्रोत कोड (एपीआई 16) में देख सकते हैं।

final Resources.Theme theme = context.getTheme();

// TextAppearance is inspected first, but let observe it later

TypedArray a = theme.obtainStyledAttributes(
            attrs, com.android.internal.R.styleable.TextView, defStyle, 0);

int n = a.getIndexCount();
for (int i = 0; i < n; i++) 
{
    int attr = a.getIndex(i);
    // huge switch with pattern value=a.getXXX(attr) <=> a.getXXX(a.getIndex(i))
}
a.recycle();

हम यहां क्या देख सकते हैं?
obtainStyledAttributes(AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes)
प्रलेखन के अनुसार विषय द्वारा गुण सेट की प्रक्रिया की जाती है। गुण मान को चरण दर चरण संकलित किया जाता है। पहले विशेषताओं को थीम से भर दिया जाता है, फिर मूल्यों को स्टाइल से मानों द्वारा प्रतिस्थापित किया जाता है, और विशेष रूप से एक्सएमएल के लिए अंत में सटीक मान दूसरों को प्रतिस्थापित करते हैं।
अनुरोधित विशेषताओं की सरणी - com.android.internal.R.styleable.TextView
यह स्थिरांक की एक साधारण सारणी है। यदि हम मानक विशेषताओं का अनुरोध कर रहे हैं, तो हम इस सरणी को मैन्युअल रूप से बना सकते हैं।

दस्तावेज़ीकरण में क्या उल्लेख नहीं किया गया है - परिणाम का क्रम टाइप किया हुआ तत्व।
जब attrs.xml में कस्टम दृश्य घोषित किया जाता है, तो विशेषता अनुक्रमित के लिए विशेष स्थिरांक उत्पन्न होते हैं। और हम इस तरह से मान निकाल सकते हैं a.getString(R.styleable.MyCustomView_android_text):। लेकिन मैनुअल के लिएint[] कोई स्थिरांक नहीं हैं। मुझे लगता है, कि getXXXValue (arrayIndex) ठीक काम करेगा।

और अन्य प्रश्न यह है: "हम आंतरिक स्थिरांक को कैसे बदल सकते हैं, और मानक विशेषताओं का अनुरोध कर सकते हैं?" हम android.R.attr। * मान का उपयोग कर सकते हैं।

इसलिए यदि हम मानक टेक्स्टएपियरेंस विशेषता का उपयोग कस्टम दृश्य में करना चाहते हैं और इसके मानों को कंस्ट्रक्टर में पढ़ना चाहते हैं, तो हम इस तरह से टेक्स्ट कोड से कोड को संशोधित कर सकते हैं:

ColorStateList textColorApp = null;
int textSize = 15;
int typefaceIndex = -1;
int styleIndex = -1;

Resources.Theme theme = context.getTheme();

TypedArray a = theme.obtainStyledAttributes(attrs, R.styleable.CustomLabel, defStyle, 0);
TypedArray appearance = null;
int apResourceId = a.getResourceId(R.styleable.CustomLabel_android_textAppearance, -1);
a.recycle();
if (apResourceId != -1)
{
    appearance = 
        theme.obtainStyledAttributes(apResourceId, new int[] { android.R.attr.textColor, android.R.attr.textSize, 
            android.R.attr.typeface, android.R.attr.textStyle });
}
if (appearance != null)
{
    textColorApp = appearance.getColorStateList(0);
    textSize = appearance.getDimensionPixelSize(1, textSize);
    typefaceIndex = appearance.getInt(2, -1);
    styleIndex = appearance.getInt(3, -1);

    appearance.recycle();
}

जहाँ CustomLabel परिभाषित किया गया है:

<declare-styleable name="CustomLabel">
    <!-- Label text. -->
    <attr name="android:text" />
    <!-- Label text color. -->
    <attr name="android:textColor" />
    <!-- Combined text appearance properties. -->
    <attr name="android:textAppearance" />
</declare-styleable>

हो सकता है, मैं किसी तरह से गलत हूं, लेकिन getStyledAttributes () पर Android प्रलेखन बहुत खराब है।

मानक UI घटक का विस्तार

उसी समय हम अपने सभी घोषित विशेषताओं का उपयोग करके, केवल मानक UI घटक का विस्तार कर सकते हैं। यह दृष्टिकोण इतना अच्छा नहीं है, क्योंकि उदाहरण के लिए TextView बहुत सारे गुणों की घोषणा करता है। और यह ऑनमरीन () और ऑनड्राइव () में पूर्ण कार्यक्षमता को लागू करना असंभव होगा।

लेकिन हम कस्टम घटक के सैद्धांतिक व्यापक पुन: उपयोग का त्याग कर सकते हैं। "मुझे पता है कि मैं कौन सी सुविधाओं का उपयोग करूंगा", और किसी के साथ कोड साझा न करें।

फिर हम कंस्ट्रक्टर को लागू कर सकते हैं CustomComponent(Context, AttributeSet, defStyle)। कॉल करने के बाद super(...)हमारे पास सभी विशेषताएँ पार्स होंगी और गेट्टर विधियों के माध्यम से उपलब्ध होंगी।


एंड्रॉइड करें: xxx पूर्वनिर्धारित विशेषताएं ग्रहण डिजाइनर में काम करती हैं?
डेज

इस तरह की विशेषताओं को संपत्ति संपादक में ग्रहण एडीटी प्लगइन द्वारा मान्यता प्राप्त है। मैं अपनी शैली से चूक देख सकता हूं, अगर कुछ मूल्यों को परिभाषित नहीं किया गया है। और अपनी कक्षा में @RemoteView एनोटेशन जोड़ना न भूलें।
yuriy.weiss

यह काम नहीं कर सकता। ग्रहण getText के लिए nulls को लोड करता रहता है और android.content.res.es फेंक देता है। getResourceId के लिए $ NotFoundException, हालांकि ऐप एक डिवाइस पर अच्छी तरह से चलता है।
डेज

क्षमा करें, मैं आपकी मदद नहीं कर सकता। मैंने संभावनाओं का परीक्षण करने के लिए केवल डेमो प्रोजेक्ट बनाया है, और ऐसी त्रुटियों को पूरा नहीं किया है।
yuriy.weiss

यह कस्टम दृश्य के कस्टम विशेषताओं को मैप करने से बहुत बेहतर है, अंतर्निहित अंतर्निर्मित विशेषताओं को अपने भीतर सम्‍मिलित विचारों के लिए।
समिस

13

ऐसा लगता है कि Google ने अपने डेवलपर पृष्ठ को अपडेट किया है और वहां विभिन्न प्रशिक्षणों को जोड़ा है।

उनमें से एक कस्टम विचारों के निर्माण से संबंधित है और यहां पाया जा सकता है


5

पहले उत्तर के लिए बहुत बहुत धन्यवाद।

मेरे लिए, मुझे इसके साथ सिर्फ एक समस्या थी। मेरे विचार को बढ़ाते समय , मेरे पास एक बग था: java.lang.NoSuchMethodException: MyView (संदर्भ, गुण)

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

public MyView(Context context, AttributeSet attrs) {
     super(context, attrs);
     // some code
}

आशा है कि यह मदद करेगा!


0

आप किसी भी लेआउट फ़ाइल को अन्य लेआउट फ़ाइल में शामिल कर सकते हैं-

             <RelativeLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dp"
                android:layout_marginRight="30dp" >

                <include
                    android:id="@+id/frnd_img_file"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    layout="@layout/include_imagefile"/>

                <include
                    android:id="@+id/frnd_video_file"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    layout="@layout/include_video_lay" />

                <ImageView
                    android:id="@+id/downloadbtn"
                    android:layout_width="30dp"
                    android:layout_height="30dp"
                    android:layout_centerInParent="true"
                    android:src="@drawable/plus"/>
            </RelativeLayout>

यहाँ शामिल टैग में लेआउट फ़ाइलें अन्य हैं। एक ही Res फ़ोल्डर में .xml लेआउट फ़ाइलें।


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