मैं XML का उपयोग करके Android UI तत्व की घोषणा कैसे करूं?
मैं XML का उपयोग करके Android UI तत्व की घोषणा कैसे करूं?
जवाबों:
Android डेवलपर गाइड में बिल्डिंग कस्टम कंपोनेंट्स नामक एक सेक्शन है । दुर्भाग्य से, एक्सएमएल विशेषताओं की चर्चा केवल लेआउट फ़ाइल के अंदर नियंत्रण की घोषणा को कवर करती है और वास्तव में वर्ग आरंभीकरण के अंदर मूल्यों को संभालना नहीं है। कदम इस प्रकार हैं:
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
उनके प्रकार को घोषित करने की आवश्यकता है। सुपरक्लास में घोषित किया गया टैग उप-वर्गों में उपलब्ध होगा बिना पुनर्वितरित किए।
चूंकि दो निर्माणकर्ता हैं जो 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
, क्योंकि इस धागे के अनुसार यह भविष्य में बदल सकता है। यह अभी भी प्रलेखन में है क्योंकि एक ही स्थान पर इन सभी स्थिरांक को देखना उपयोगी है।
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 लेबल दृश्य नमूना देखें।
TypedArray a=context.obtainStyledAttributes(attrs, R.styleable.LabelView);
CharSequences=a.getString(R.styleable.LabelView_text);
<declare-styleable name="LabelView">
<attr name="text"format="string"/>
<attr name="textColor"format="color"/>
<attr name="textSize"format="dimension"/>
</declare-styleable>
<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"
महान संदर्भ। धन्यवाद! इसके अतिरिक्त:
यदि आपके पास एक लाइब्रेरी प्रोजेक्ट शामिल है, जो एक कस्टम दृश्य के लिए कस्टम विशेषताओं की घोषणा करता है, तो आपको अपने प्रोजेक्ट के नाम स्थान की घोषणा करनी होगी, न कि लाइब्रेरी की। उदाहरण के लिए:
यह देखते हुए कि लाइब्रेरी में पैकेज "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" />
xmlns:app="http://schemas.android.com/apk/res-auto"
टिप्पणी 57 देखें कोड में देखें।
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]
सबसे अधिक वोट किए गए उत्तर के अलावा।
जब हम एंड्रॉइड का उपयोग करके कस्टम दृश्य बनाते हैं, तो मैं कुछ शब्दों को जोड़ना चाहता हूं। खासकर जब हम 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 घटक का विस्तार कर सकते हैं। यह दृष्टिकोण इतना अच्छा नहीं है, क्योंकि उदाहरण के लिए TextView बहुत सारे गुणों की घोषणा करता है। और यह ऑनमरीन () और ऑनड्राइव () में पूर्ण कार्यक्षमता को लागू करना असंभव होगा।
लेकिन हम कस्टम घटक के सैद्धांतिक व्यापक पुन: उपयोग का त्याग कर सकते हैं। "मुझे पता है कि मैं कौन सी सुविधाओं का उपयोग करूंगा", और किसी के साथ कोड साझा न करें।
फिर हम कंस्ट्रक्टर को लागू कर सकते हैं CustomComponent(Context, AttributeSet, defStyle)
। कॉल करने के बाद super(...)
हमारे पास सभी विशेषताएँ पार्स होंगी और गेट्टर विधियों के माध्यम से उपलब्ध होंगी।
पहले उत्तर के लिए बहुत बहुत धन्यवाद।
मेरे लिए, मुझे इसके साथ सिर्फ एक समस्या थी। मेरे विचार को बढ़ाते समय , मेरे पास एक बग था: java.lang.NoSuchMethodException: MyView (संदर्भ, गुण)
मैंने एक नया निर्माता बनाकर इसे हल किया:
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
// some code
}
आशा है कि यह मदद करेगा!
आप किसी भी लेआउट फ़ाइल को अन्य लेआउट फ़ाइल में शामिल कर सकते हैं-
<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 लेआउट फ़ाइलें।