วิธีแก้ปัญหาที่ระบุโดย @ (Ted Hopp) ใช้งานได้ แต่ต้องการการแก้ไขเล็กน้อย: ในตัวเลือกรายการระบุสถานะต้องใช้คำนำหน้า "app:" มิฉะนั้นตัวจ่ายลมจะไม่รู้จักเนมสเปซที่ถูกต้องและจะล้มเหลวอย่างเงียบ ๆ อย่างน้อยนี่คือสิ่งที่เกิดขึ้นกับฉัน
ให้ฉันรายงานโซลูชั่นทั้งหมดพร้อมที่นี่โดยมีรายละเอียดเพิ่มเติม
ก่อนอื่นให้สร้างไฟล์ "res / values / 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>
จากนั้นกำหนดคลาสที่คุณกำหนดเอง ตัวอย่างเช่นมันอาจเป็นคลาส "FoodButton" มาจากคลาส "ปุ่ม" คุณจะต้องใช้ตัวสร้าง; ใช้อันนี้ซึ่งดูเหมือนจะเป็นคนที่ใช้โดย inflater:
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>
แจ้งให้ทราบล่วงหน้าคำนำหน้า "แอพ:" ในขณะที่สถานะ Android มาตรฐานคุณจะต้องใช้คำนำหน้า "android:" XML เนมสเปซมีความสำคัญสำหรับการตีความที่ถูกต้องโดยผู้จัดทำและขึ้นอยู่กับประเภทของโครงการที่คุณกำลังเพิ่มคุณสมบัติ หากเป็นแอปพลิเคชันให้แทนที่com.mydomain.mypackageด้วยชื่อแพ็คเกจจริงของแอปพลิเคชันของคุณ (ยกเว้นชื่อแอปพลิเคชัน) หากเป็นห้องสมุดคุณต้องใช้ "http://schemas.android.com/apk/res-auto" (และใช้ Tools R17 หรือใหม่กว่า) มิฉะนั้นคุณจะได้รับข้อผิดพลาด runtime
หมายเหตุสองประการ:
ดูเหมือนว่าคุณไม่จำเป็นต้องเรียกใช้ฟังก์ชัน "refreshDrawableState" อย่างน้อยโซลูชันจะทำงานได้ดีอย่างที่เป็นอยู่ในกรณีของฉัน
ในการใช้คลาสที่กำหนดเองของคุณในไฟล์เลย์เอาต์ xml คุณจะต้องระบุชื่อแบบเต็ม (เช่น com.mydomain.mypackage.FoodButton)
คุณสามารถเป็นสถานะมาตรฐาน weel mix-up (เช่น android: กด, android: เปิดใช้งาน, android: เลือก) ด้วยสถานะที่กำหนดเองเพื่อแสดงชุดค่าสถานะที่ซับซ้อนมากขึ้น