@ (টেড হপ্প) দ্বারা নির্দেশিত সমাধানটি কাজ করে তবে কিছুটা সংশোধন দরকার: নির্বাচক হিসাবে আইটেমটির একটি "অ্যাপ:" উপসর্গের প্রয়োজন হয়, অন্যথায় স্ফীতকারী নাম স্থানটি সঠিকভাবে চিনতে পারে না, এবং নিঃশব্দে ব্যর্থ হবে; অন্তত আমার ক্ষেত্রে এটি ঘটে।
আমাকে আরও কিছু বিশদ সহ পুরো সমাধানটি এখানে প্রতিবেদন করার অনুমতি দিন:
প্রথমে "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;
}
অবশেষে, এই ধাঁধার সবচেয়ে সূক্ষ্ম টুকরা; নির্বাচক স্টেটলিস্টড্রেবলের সংজ্ঞা দিচ্ছেন যা আপনি আপনার উইজেটের পটভূমি হিসাবে ব্যবহার করবেন। এটি ফাইল "রেজো / ড্রইয়েবল / ফুড_বুটন.এক্সএমএল":
<?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 বা তার পরে ব্যবহার করা উচিত) অথবা আপনি রানটাইম ত্রুটি পাবেন।
কয়েকটি নোট:
মনে হচ্ছে আপনার "রিফ্রেশড্রেইবল স্টেট" ফাংশনটি কল করার দরকার নেই, আমার ক্ষেত্রে কমপক্ষে সমাধানটি যেমন কাজ করে তেমনি
বিন্যাসের এক্সএমএল ফাইলে আপনার কাস্টম ক্লাসটি ব্যবহার করতে, আপনাকে পুরোপুরি যোগ্যতাসম্পন্ন নামটি নির্দিষ্ট করতে হবে (যেমন com.mydomain.mypackage.FoodButton)
আরও জটিল রাষ্ট্রের সংমিশ্রণের প্রতিনিধিত্ব করার জন্য আপনি কাস্টম রাজ্যের সাথে উইল মিক্স-আপ স্ট্যান্ডার্ড স্টেটস (যেমন অ্যান্ড্রয়েড: চাপা, অ্যান্ড্রয়েড: সক্ষম, অ্যান্ড্রয়েড: নির্বাচিত) হিসাবে করতে পারেন