मुझे अपनी खुद की विशेषताओं को लागू करने की आवश्यकता है जैसे कि com.android.R.attr
आधिकारिक दस्तावेज़ीकरण में कुछ भी नहीं मिला है, इसलिए मुझे इन कोड को परिभाषित करने और उन्हें अपने कोड से कैसे उपयोग करना है, इसके बारे में जानकारी चाहिए।
मुझे अपनी खुद की विशेषताओं को लागू करने की आवश्यकता है जैसे कि com.android.R.attr
आधिकारिक दस्तावेज़ीकरण में कुछ भी नहीं मिला है, इसलिए मुझे इन कोड को परिभाषित करने और उन्हें अपने कोड से कैसे उपयोग करना है, इसके बारे में जानकारी चाहिए।
जवाबों:
वर्तमान में सबसे अच्छा प्रलेखन स्रोत है। आप इसे यहाँ देख सकते हैं (attrs.xml) ।
आप शीर्ष <resources>
तत्व में या किसी <declare-styleable>
तत्व के अंदर विशेषताओं को परिभाषित कर सकते हैं । यदि मैं एक से अधिक जगह पर एक attr का उपयोग करने जा रहा हूँ, तो मैं इसे मूल तत्व में डाल देता हूँ। ध्यान दें, सभी विशेषताएँ समान वैश्विक नाम स्थान साझा करती हैं। इसका मतलब है कि भले ही आप एक <declare-styleable>
तत्व के अंदर एक नई विशेषता का निर्माण करते हैं, इसका उपयोग इसके बाहर किया जा सकता है और आप एक अलग प्रकार के नाम के साथ एक और विशेषता नहीं बना सकते हैं।
एक <attr>
तत्व में दो xml विशेषताएँ हैं name
और format
। name
आपको इसे कुछ कॉल करने देता है और इस तरह से आप कोड, उदाहरण के लिए इसे समाप्त करते हैं R.attr.my_attribute
। जिस format
विशेषता को आप चाहते हैं उसके आधार पर विशेषता के भिन्न मूल्य हो सकते हैं।
आप |
उदाहरण के लिए, कई प्रकारों का उपयोग करके प्रारूप सेट कर सकते हैं , जैसे format="reference|color"
।
enum
विशेषताओं को निम्नानुसार परिभाषित किया जा सकता है:
<attr name="my_enum_attr">
<enum name="value1" value="1" />
<enum name="value2" value="2" />
</attr>
flag
मूल्यों को परिभाषित करने की आवश्यकता के अलावा विशेषताएँ समान हैं ताकि उन्हें एक साथ बिट या ऑर्ड किया जा सके:
<attr name="my_flag_attr">
<flag name="fuzzy" value="0x01" />
<flag name="cold" value="0x02" />
</attr>
विशेषताओं के अतिरिक्त <declare-styleable>
तत्व है। यह आपको उन विशेषताओं को परिभाषित करने की अनुमति देता है जिनका एक कस्टम दृश्य उपयोग कर सकता है। आप एक <attr>
तत्व को निर्दिष्ट करके ऐसा करते हैं , अगर यह पहले से परिभाषित किया गया था तो आप निर्दिष्ट नहीं करते हैं format
। यदि आप एक एंड्रॉइड एट्री का पुन: उपयोग करना चाहते हैं, उदाहरण के लिए, एंड्रॉइड: गुरुत्वाकर्षण, तो आप name
निम्नानुसार ऐसा कर सकते हैं ।
कस्टम दृश्य का एक उदाहरण <declare-styleable>
:
<declare-styleable name="MyCustomView">
<attr name="my_custom_attribute" />
<attr name="android:gravity" />
</declare-styleable>
अपने कस्टम दृश्य पर XML में अपनी कस्टम विशेषताओं को परिभाषित करते समय आपको कुछ चीजें करने की आवश्यकता होती है। पहले आपको अपनी विशेषताओं को खोजने के लिए एक नाम स्थान की घोषणा करनी चाहिए। आप इसे रूट लेआउट तत्व पर करते हैं। आम तौर पर केवल है xmlns:android="http://schemas.android.com/apk/res/android"
। अब आपको भी जोड़ना होगा xmlns:whatever="http://schemas.android.com/apk/res-auto"
।
उदाहरण:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:whatever="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<org.example.mypackage.MyCustomView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
whatever:my_custom_attribute="Hello, world!" />
</LinearLayout>
अंत में, उस कस्टम विशेषता को एक्सेस करने के लिए आप सामान्य रूप से अपने कस्टम व्यू के कंस्ट्रक्टर में निम्नानुसार करते हैं।
public MyCustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyCustomView, defStyle, 0);
String str = a.getString(R.styleable.MyCustomView_my_custom_attribute);
//do something with str
a.recycle();
}
समाप्त। :)
View
: github.com/commonsguy/cw-advandroid/tree/master/Views/…
xmlns:my="http://schemas.android.com/apk/lib/my.namespace"
- कोई कॉपीिंग attrs.xml नहीं। ध्यान दें नामस्थान URI पथ / apk / * lib * नहीं / apk / res होना चाहिए।
apk/lib
ट्रिक ने लाइब्रेरी प्रोजेक्ट से संदर्भ प्रारूप के साथ कस्टम विशेषताओं पर मेरे लिए काम नहीं किया। क्या किया था काम उपयोग के लिए गया था apk/res-auto
के रूप में सुझाव दिया, stackoverflow.com/a/13420366/22904 और बस से नीचे भी stackoverflow.com/a/10217752
enum
और flag
पूर्व हमें एक और केवल एक मूल्य लेने की सुविधा देता है, बाद हमें कई गठबंधन की सुविधा देता है। मैंने यहाँ एक ऐसे ही प्रश्न का लंबा उत्तर लिखा है , और अब मुझे यह प्रश्न मिला है कि मैं उससे जुड़ा था।
a.recycle()
स्मृति को मुक्त करने के लिए यहां बहुत महत्वपूर्ण है
Qberticus का उत्तर अच्छा है, लेकिन एक उपयोगी विवरण गायब है। यदि आप इन्हें पुस्तकालय में प्रतिस्थापित कर रहे हैं:
xmlns:whatever="http://schemas.android.com/apk/res/org.example.mypackage"
साथ में:
xmlns:whatever="http://schemas.android.com/apk/res-auto"
अन्यथा लाइब्रेरी का उपयोग करने वाले एप्लिकेशन में रनटाइम त्रुटियां होंगी।
ऊपर दिया गया उत्तर एक-दो चीजों के अलावा हर चीज को बहुत विस्तार से कवर करता है।
सबसे पहले, यदि कोई शैली नहीं है, तो (Context context, AttributeSet attrs)
वरीयता को तत्काल करने के लिए विधि हस्ताक्षर का उपयोग किया जाएगा। इस मामले में सिर्फ context.obtainStyledAttributes(attrs, R.styleable.MyCustomView)
टाइप करने के लिए उपयोग करेंआधार।
दूसरी बात यह नहीं है कि प्लाउरल संसाधनों (मात्रा के तार) से कैसे निपटा जाए। इन्हें TypedArray का उपयोग करके निपटाया नहीं जा सकता। यहाँ मेरा SeekBarPreference से एक कोड स्निपेट है जो वरीयता के सारांश को वरीयता के मूल्य के अनुसार इसके मूल्य को सेट करता है। यदि वरीयता के लिए xml Android सेट करता है: एक पाठ स्ट्रिंग या एक स्ट्रिंग का सारांश, वरीयता के मूल्य को स्ट्रिंग में स्वरूपित किया जाता है (यह मान लेने के लिए इसमें% d होना चाहिए)। यदि एंड्रॉइड: सारांश को प्लोरल्स संसाधन पर सेट किया जाता है, तो इसका उपयोग परिणाम को प्रारूपित करने के लिए किया जाता है।
// Use your own name space if not using an android resource.
final static private String ANDROID_NS =
"http://schemas.android.com/apk/res/android";
private int pluralResource;
private Resources resources;
private String summary;
public SeekBarPreference(Context context, AttributeSet attrs) {
// ...
TypedArray attributes = context.obtainStyledAttributes(
attrs, R.styleable.SeekBarPreference);
pluralResource = attrs.getAttributeResourceValue(ANDROID_NS, "summary", 0);
if (pluralResource != 0) {
if (! resources.getResourceTypeName(pluralResource).equals("plurals")) {
pluralResource = 0;
}
}
if (pluralResource == 0) {
summary = attributes.getString(
R.styleable.SeekBarPreference_android_summary);
}
attributes.recycle();
}
@Override
public CharSequence getSummary() {
int value = getPersistedInt(defaultValue);
if (pluralResource != 0) {
return resources.getQuantityString(pluralResource, value, value);
}
return (summary == null) ? null : String.format(summary, value);
}
notifyChanged()
वरीयता की onDialogClosed
विधि में कॉल करने की आवश्यकता है ।पारंपरिक दृष्टिकोण बॉयलरप्लेट कोड और अनाड़ी संसाधन हैंडलिंग से भरा है। इसलिए मैंने स्पाईग्लास फ्रेमवर्क बनाया । यह कैसे काम करता है यह प्रदर्शित करने के लिए, यहां एक उदाहरण दिखाया गया है कि एक कस्टम दृश्य कैसे बनाया जाए जो स्ट्रिंग शीर्षक प्रदर्शित करता है।
चरण 1: एक कस्टम व्यू क्लास बनाएं।
public class CustomView extends FrameLayout {
private TextView titleView;
public CustomView(Context context) {
super(context);
init(null, 0, 0);
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs, 0, 0);
}
public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs, defStyleAttr, 0);
}
@RequiresApi(21)
public CustomView(
Context context,
AttributeSet attrs,
int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(attrs, defStyleAttr, defStyleRes);
}
public void setTitle(String title) {
titleView.setText(title);
}
private void init(AttributeSet attrs, int defStyleAttr, int defStyleRes) {
inflate(getContext(), R.layout.custom_view, this);
titleView = findViewById(R.id.title_view);
}
}
चरण 2: values/attrs.xml
संसाधन फ़ाइल में एक स्ट्रिंग विशेषता को परिभाषित करें :
<resources>
<declare-styleable name="CustomView">
<attr name="title" format="string"/>
</declare-styleable>
</resources>
चरण 3: @StringHandler
इस setTitle
तरीके को विशेषता मान को देखने के लिए स्पेलग्लास फ्रेमवर्क को बताने के लिए एनोटेशन को लागू करें जब दृश्य फुलाया जाता है।
@HandlesString(attributeId = R.styleable.CustomView_title)
public void setTitle(String title) {
titleView.setText(title);
}
अब जब आपकी कक्षा में स्पाईग्लास एनोटेशन है, तो स्पाईग्लास फ्रेमवर्क इसे संकलन-समय पर पता लगाएगा और स्वचालित रूप से CustomView_SpyglassCompanion
क्लास उत्पन्न करेगा ।
चरण 4: कस्टम दृश्य की init
विधि में उत्पन्न वर्ग का उपयोग करें:
private void init(AttributeSet attrs, int defStyleAttr, int defStyleRes) {
inflate(getContext(), R.layout.custom_view, this);
titleView = findViewById(R.id.title_view);
CustomView_SpyglassCompanion
.builder()
.withTarget(this)
.withContext(getContext())
.withAttributeSet(attrs)
.withDefaultStyleAttribute(defStyleAttr)
.withDefaultStyleResource(defStyleRes)
.build()
.callTargetMethodsNow();
}
बस। अब जब आप एक्सएमएल से क्लास को इंस्टेंट करते हैं, तो स्पाईग्लास साथी विशेषताओं की व्याख्या करता है और आवश्यक विधि कॉल करता है। उदाहरण के लिए, यदि हम निम्नलिखित लेआउट को बढ़ाते हैं, तो setTitle
इसे "Hello, World!"
तर्क के रूप में कहा जाएगा ।
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:width="match_parent"
android:height="match_parent">
<com.example.CustomView
android:width="match_parent"
android:height="match_parent"
app:title="Hello, World!"/>
</FrameLayout>
ढांचा स्ट्रिंग संसाधनों तक सीमित नहीं है, अन्य संसाधन प्रकारों को संभालने के लिए बहुत सारे एनोटेशन हैं। इसमें डिफ़ॉल्ट मानों को परिभाषित करने और प्लेसहोल्डर मानों में पास करने के लिए भी एनोटेशन हैं यदि आपके तरीकों में कई पैरामीटर हैं।
अधिक जानकारी और उदाहरणों के लिए Github repo पर एक नज़र डालें।
android:title="@{"Hello, world!"}"
।
यदि आप तत्व format
से विशेषता को छोड़ देते हैं attr
, तो आप इसका उपयोग XML लेआउट से एक क्लास को संदर्भित करने के लिए कर सकते हैं।
Refactor > Rename
काम करता हैFind Usages
काम करता है... / src / main / res / values / attrs.xmlformat
में एक विशेषता निर्दिष्ट न करें
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyCustomView">
....
<attr name="give_me_a_class"/>
....
</declare-styleable>
</resources>
इसे कुछ लेआउट फ़ाइल में उपयोग करें ... / src / main / res / layout / activity__main_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<SomeLayout
xmlns:app="http://schemas.android.com/apk/res-auto">
<!-- make sure to use $ dollar signs for nested classes -->
<MyCustomView
app:give_me_a_class="class.type.name.Outer$Nested/>
<MyCustomView
app:give_me_a_class="class.type.name.AnotherClass/>
</SomeLayout>
अपने दृश्य आरंभीकरण कोड में कक्षा को पार्स करें ... / src / main / java /.../ MyCustomView.kt
class MyCustomView(
context:Context,
attrs:AttributeSet)
:View(context,attrs)
{
// parse XML attributes
....
private val giveMeAClass:SomeCustomInterface
init
{
context.theme.obtainStyledAttributes(attrs,R.styleable.ColorPreference,0,0).apply()
{
try
{
// very important to use the class loader from the passed-in context
giveMeAClass = context::class.java.classLoader!!
.loadClass(getString(R.styleable.MyCustomView_give_me_a_class))
.newInstance() // instantiate using 0-args constructor
.let {it as SomeCustomInterface}
}
finally
{
recycle()
}
}
}