कस्टम बटन स्थिति कैसे जोड़ें


132

उदाहरण के लिए, डिफ़ॉल्ट बटन में इसके राज्यों और पृष्ठभूमि छवियों के बीच निम्न निर्भरताएं हैं:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_window_focused="false" android:state_enabled="true"
        android:drawable="@drawable/btn_default_normal" />
    <item android:state_window_focused="false" android:state_enabled="false"
        android:drawable="@drawable/btn_default_normal_disable" />
    <item android:state_pressed="true" 
        android:drawable="@drawable/btn_default_pressed" />
    <item android:state_focused="true" android:state_enabled="true"
        android:drawable="@drawable/btn_default_selected" />
    <item android:state_enabled="true"
        android:drawable="@drawable/btn_default_normal" />
    <item android:state_focused="true"
        android:drawable="@drawable/btn_default_normal_disable_focused" />
    <item
        android:drawable="@drawable/btn_default_normal_disable" />
</selector>

मैं अपनी स्वयं की कस्टम स्थिति (smth like android:state_custom) को कैसे परिभाषित कर सकता हूं , इसलिए मैं इसका उपयोग अपने बटन दृश्य स्वरूप को गतिशील रूप से बदलने के लिए कर सकता हूं?


मैं एक एडिटटेक्स्ट दृश्य के लिए अतिरिक्त राज्यों को निर्धारित करना चाहता था जब दो पासवर्ड बॉक्स थोड़ा चेकमार्क दिखाने के लिए मेल खाते हैं।
नाथन श्वानमैन

जवाबों:


275

@ (टेड होप) द्वारा इंगित किया गया समाधान काम करता है, लेकिन इसमें थोड़ा सुधार करने की आवश्यकता है: चयनकर्ता में, आइटम राज्यों को एक "ऐप:" उपसर्ग की आवश्यकता होती है, अन्यथा फ्लोटर नामस्थान को सही ढंग से पहचान नहीं पाएगा, और चुपचाप विफल हो जाएगा; कम से कम मेरे साथ ऐसा ही होता है।

मुझे कुछ और विवरणों के साथ संपूर्ण समाधान की रिपोर्ट करने की अनुमति दें:

सबसे पहले, फ़ाइल "Res / मान / attrs.xml" बनाएं:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="food">
        <attr name="state_fried" format="boolean" />
        <attr name="state_baked" format="boolean" />
    </declare-styleable>
</resources>

फिर अपने कस्टम वर्ग को परिभाषित करें। उदाहरण के लिए, यह एक वर्ग "फूडबटन" हो सकता है, जो "बटन" से लिया गया है। आपको एक कंस्ट्रक्टर लागू करना होगा; इसे लागू करें, जो कि इनफ्लोटर द्वारा उपयोग किया जाने वाला लगता है:

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

व्युत्पन्न वर्ग के शीर्ष पर:

private static final int[] STATE_FRIED = {R.attr.state_fried};
private static final int[] STATE_BAKED = {R.attr.state_baked};

इसके अलावा, आपके राज्य चर:

private boolean mIsFried = false;
private boolean mIsBaked = false;

और बसने वालों की एक जोड़ी:

public void setFried(boolean isFried) {mIsFried = isFried;}
public void setBaked(boolean isBaked) {mIsBaked = isBaked;}

फिर कार्य को ओवरराइड करें "onCreateDrawableState":

@Override
protected int[] onCreateDrawableState(int extraSpace) {
    final int[] drawableState = super.onCreateDrawableState(extraSpace + 2);
    if (mIsFried) {
        mergeDrawableStates(drawableState, STATE_FRIED);
    }
    if (mIsBaked) {
        mergeDrawableStates(drawableState, STATE_BAKED);
    }
    return drawableState;
}

अंत में, इस पहेली का सबसे नाजुक टुकड़ा; चयनकर्ता StateListDrawable को परिभाषित करता है जिसे आप अपने विजेट के लिए पृष्ठभूमि के रूप में उपयोग करेंगे। यह फ़ाइल "res / drawable / food_button.xml" है:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res/com.mydomain.mypackage">
<item
    app:state_baked="true"
    app:state_fried="false"
    android:drawable="@drawable/item_baked" />
<item
    app:state_baked="false"
    app:state_fried="true"
    android:drawable="@drawable/item_fried" />
<item
    app:state_baked="true"
    app:state_fried="true"
    android:drawable="@drawable/item_overcooked" />
<item
    app:state_baked="false"
    app:state_fried="false"
    android:drawable="@drawable/item_raw" />
</selector>

"ऐप:" उपसर्ग को नोटिस करें, जबकि मानक एंड्रॉइड राज्यों के साथ आपने उपसर्ग "एंड्रॉइड:" का उपयोग किया होगा। एक्सएमएल नेमस्पेस एक सही व्याख्या के लिए महत्वपूर्ण है जो कि इनफ्लोटर द्वारा सही व्याख्या करता है और उस परियोजना के प्रकार पर निर्भर करता है जिसमें आप विशेषताएँ जोड़ रहे हैं। यदि यह एक अनुप्रयोग है, तो com.mydomain.mypackage को अपने आवेदन के वास्तविक पैकेज नाम (आवेदन नाम को छोड़कर) के साथ बदलें । यदि यह एक पुस्तकालय है, तो आपको "http://schemas.android.com/apk/res-auto" (और उपकरण R17 या बाद का उपयोग करना होगा) का उपयोग करना होगा या आपको रनटाइम त्रुटियाँ मिलेंगी।

नोटों की एक जोड़ी:

  • ऐसा लगता है कि आपको "रिफ्रेशडेबलटेस्ट" फ़ंक्शन को कॉल करने की आवश्यकता नहीं है, कम से कम समाधान मेरे मामले में अच्छी तरह से काम करता है

  • लेआउट xml फ़ाइल में अपने कस्टम वर्ग का उपयोग करने के लिए, आपको पूरी तरह से योग्य नाम (जैसे com.mydomain.mypackage.FoodButton) निर्दिष्ट करना होगा

  • आप और अधिक जटिल राज्य संयोजनों का प्रतिनिधित्व करने के लिए कस्टम राज्यों के साथ मिलाने के लिए मानक राज्यों (जैसे कि android: दबाया, Android: सक्षम, Android: चयनित) को मिला सकते हैं


3
अद्यतन: यदि कस्टम क्लास बटन के बजाय TextView से प्राप्त होती है, तो ताज़ा करने के लिए कॉल करने योग्य प्रतीत होता है, अन्यथा विजेट उपस्थिति अपडेट नहीं होती है। कॉल को बसने वालों में रखा जाएगा। मैंने अन्य वर्गों की कोशिश नहीं की है। टेस्ट एक फरो डिवाइस पर किए गए।
जियोर्जियो बारचीसी

17
refreshDrawableStateनिश्चित रूप से महत्वपूर्ण है। मुझे बिल्कुल यकीन नहीं है कि वास्तव में इसकी जरूरत है। लेकिन मेरे मामले में राज्य को प्रोग्रामेटिक रूप से सेट करते समय इसकी आवश्यकता थी। मुझे लगता है कि यह संभवतः व्यू क्लास से ऑनटचवेंट में स्वचालित रूप से कहा जाता है। बेहतर होगा कि मैं इसे सेटलेक्टेड विधि में जोड़ दूं।
बुर्जी

1
GiorgioBarchiesi, मेरे पास दो कस्टम बटन हैं, और जब मैं एक बटन के ऑनक्लिक इवेंट से दोनों बटन की स्थिति को बदलने की कोशिश करता हूं, तो केवल क्लिक किए गए बटन को बदल दिया जाएगा, मुझे लगता है कि @buergi सही है कि रीफ्रेश करने योग्य स्ट्रेट विधि को बुलाया जाता है onClickEvent। आपके अद्भुत ट्यूटोरियल के लिए फिर से धन्यवाद :)
बोल्टन

2
लेकिन आप कस्टम राज्यों का उपयोग कैसे कर सकते हैं जो नहीं हैं boolean? या चयनकर्ता केवल बूलियन पर काम कर रहे हैं?
पीटरडक

2
यह कैसे काम करता है? मेरा मतलब है, कैसे विशेषता सच / झूठ के लिए अद्यतन हो जाती है? इसे कौन अपडेट करता है? क्या केवल स्थानीय वैरिएबल सत्य होने पर, ड्रॉब्लेट को विलय करता है, विशेषता की स्थिति या मूल्य को अपडेट करता है? कौन सा कोड वास्तव में R.attr.state_fried को अपडेट करेगा?
kAmol

10

यह थ्रेड दिखाता है कि कस्टम स्टेट्स को बटन और इस तरह कैसे जोड़ा जाए। (यदि आप अपने ब्राउज़र में नए Google समूह नहीं देख सकते हैं, तो यहां थ्रेड की एक प्रति है ।)


+1 बहुत बहुत धन्यवाद, टेड! अभी परेशानी का मूल चला गया है इसलिए मुझे वास्तविक क्रियान्वयन नहीं मिला। हालाँकि, मुझे अपने ग्राहक को फिर से लौटना चाहिए, मैं उस तरह से कोशिश करूँगा जैसे आपने मुझे बताया था।
विट खुद्देंको

जैसा मुझे चाहिए वैसा ही दिखता है, हालाँकि मेरे कस्टम स्टेट्स के लिए स्टेट-लिस्ट ड्रॉइंग्स नहीं बदल रहे हैं, मुझे कुछ याद आ रहा है ...
नाथन श्वानमैन

क्या आप रिफ्रेशडेबलटेबल () कह रहे हैं?
टेड हॉप

लिंक मर चुके हैं।
मिच

@ मिच - ठीक है, यह बहुत बुरा है। मैं देखूंगा कि क्या मुझे कुछ प्रतिस्थापन लिंक मिल सकते हैं। यदि नहीं, तो मैं इस उत्तर को हटा दूंगा, क्योंकि यह मूल रूप से बेकार है। इस बीच, स्वीकृत उत्तर में सभी आवश्यक जानकारी है।
टेड होप

6

कृपया refreshDrawableStateUI थ्रेड के भीतर कॉल करना न भूलें :

mHandler.post(new Runnable() {
    @Override
    public void run() {
        refreshDrawableState();
    }
});

मुझे यह पता लगाने में बहुत समय लगा कि मेरा बटन अपनी स्थिति को क्यों नहीं बदल रहा है, भले ही सब कुछ सही लगे।


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