แอตทริบิวต์ที่มีชื่อเดียวกันใน attrs.xml สำหรับมุมมองที่กำหนดเอง


180

ฉันกำลังเขียนมุมมองที่กำหนดเองไม่กี่ตัวที่ใช้แอตทริบิวต์ที่มีชื่อเดียวกันร่วมกัน ใน<declare-styleable>ส่วนที่เกี่ยวข้องในattrs.xmlฉันต้องการใช้ชื่อเดียวกันสำหรับแอตทริบิวต์:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyView1">
        <attr name="myattr1" format="string" />
        <attr name="myattr2" format="dimension" />
        ...
    </declare-styleable>

    <declare-styleable name="MyView2">
        <attr name="myattr1" format="string" />
        <attr name="myattr2" format="dimension" />
        ...
    </declare-styleable>
</resources>

ฉันได้รับข้อผิดพลาดบอกว่าmyattr1และmyattr2มีการกำหนดไว้แล้ว ฉันพบว่าฉันควรละเว้นformatแอตทริบิวต์สำหรับmyattr1และmyattr2ในMyView2แต่ถ้าฉันทำฉันได้รับข้อผิดพลาดต่อไปนี้ในคอนโซล:

[2010-12-13 23:53:11 - MyProject] ERROR: In <declare-styleable> MyView2, unable to find attribute 

มีวิธีที่ฉันสามารถทำสิ่งนี้ได้หรือไม่บางทีการกำหนดชื่อบางอย่าง (แค่เดา)

คำตอบ:


401

วิธีแก้ไข:เพียงแยกแอตทริบิวต์ทั่วไปจากทั้งสองมุมมองและเพิ่มโดยตรงเป็นลูกของ<resources>โหนด:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="myattr1" format="string" />
    <attr name="myattr2" format="dimension" />

    <declare-styleable name="MyView1">
        <attr name="myattr1" />
        <attr name="myattr2" />
        ...
    </declare-styleable>

    <declare-styleable name="MyView2">
        <attr name="myattr1" />
        <attr name="myattr2" />
        ...
    </declare-styleable>
</resources>

11
เกิดอะไรขึ้นเมื่อmyattr1เป็นสตริงMyView1และจำนวนเต็มMyView2?
foxx1337

4
ฉันไม่คิดอย่างนั้นเช่นเราสามารถมีแอตทริบิวต์ 'การวางแนว' และสำหรับบางมุมมองมันคือ 'แนวนอน' / 'แนวตั้ง' และสำหรับ 'แนวนอน' / 'แนวตั้ง' อื่น ๆ / สำหรับ 'แนวตั้ง' จากมุมมองของฉันมันเป็นข้อผิดพลาด (หรือพฤติกรรมที่ไม่สอดคล้องกันอย่างน้อย) ใน Android (โปรดจำไว้ว่า: 1. คุณลักษณะ stylable มักเริ่มต้นด้วยคำนำหน้า = ชื่อดูและ 2 หากคุณสร้างโครงการห้องสมุดแยกต่างหากสำหรับมุมมองดังกล่าว )
se.solovyev

4
เมื่อฉันทำตามคำตอบนี้ฉันได้รับ ERROR: In <declare-styleable> com_app_view_widget, unable to find attribute customAttr ทุกมุมมองฉันพยายามที่จะประกาศ ความคิดใด ๆ
Dapp

45
@Google: การออกแบบที่เส็งเคร็ง
Glenn Bech

6
@ foxx1337 <attr name="myattr1" format="string|integer" />เพียงแค่การใช้งาน ได้ผลสำหรับฉัน
Mygod

58

ฉันโพสต์คำตอบนี้เนื่องจากโซลูชันที่โพสต์ข้างต้นไม่ได้ผลสำหรับฉันใน Android Studio ฉันต้องการแบ่งปันแอตทริบิวต์ที่กำหนดเองของฉันในมุมมองที่กำหนดเองดังนั้นฉันจึงลองวิธีแก้ปัญหาข้างต้นใน Android Studio แต่ก็ไม่มีโชค ดังนั้นฉันจึงทดลองและทำมันต่อไป หวังว่ามันจะช่วยให้ใครบางคนกำลังมองหาปัญหาเดียวกัน

  <?xml version="1.0" encoding="utf-8"?>
    <resources>
    <!-- parent styleable -->
     <declare-styleable name="MyView">
         <attr name="myattr1" format="string" />
         <attr name="myattr2" format="dimension" />
     </declare-styleable>

     <!-- inheriting parent styleable -->
     <!-- also note "myBackgroundColor" belongs to child styleable"MyView1"-->
    <declare-styleable name="MyView1" parent="MyView">
        <attr name="myattr1" />
        <attr name="myattr2" />
        <attr name="myBackgroundColor" format="color"/>
    </declare-styleable>


    <!-- inheriting parent styleable -->
    <!-- same way here "myfonnt" belongs to child styelable "MyView2" -->
    <declare-styleable name="MyView2" parent="MyView">
        <attr name="myattr1" />
        <attr name="myattr2" />
        <attr name="myfont" format="string"/>
        ...
    </declare-styleable>
</resources>

สิ่งนี้ใช้ได้สำหรับฉันอย่างสมบูรณ์ เราจำเป็นต้องสร้างสไตล์ผู้ปกครองและจากนั้นเราจำเป็นต้องสืบทอดสไตล์ผู้ปกครองนั้น ตัวอย่างเช่นที่ฉันได้ทำข้างต้น: ชื่อสไตล์ MyView ผู้ปกครองและสืบทอดสิ่งนี้ไปยังสไตล์อื่น ๆ ของฉันเช่น MyView1 และ MyView2 ตามลำดับ


1
สิ่งนี้ใช้ได้สำหรับฉัน ฉันหาวิธีอ้างอิงแอตทริบิวต์ที่แยกในรหัสจากคำตอบที่ยอมรับไม่ได้
Nemanja Kovacevic

อืม .. มันแปลก .. วิธีแก้ปัญหาที่ยอมรับดูเหมือนจะทำงานได้ดีสำหรับฉัน (targetSdkVersion 27) อาจเป็นเพราะแอตทริบิวต์เช่น "text" เป็นเรื่องปกติและอาจมีอยู่ใน attrs.xml อื่น ๆ บ้างไหม?
Aba

ฉันลองด้วยชื่อที่อาจผิดปกติมากที่สุดและวิธีแก้ปัญหาที่ยอมรับก็ยังใช้ได้สำหรับฉัน
Aba

ฉันเห็นด้วยกับความคิดเห็นแรก! ไม่มีวิธีอ้างอิง attr ที่ดึงข้อมูลจาก typedArray ดังนั้นคุณต้องกำหนดผู้ปกครองที่มีสไตล์
reavcn

สำหรับการทำงานไม่ลืมที่จะอยู่ในแอตทริบิวต์นี้ผู้ปกครองและไม่ได้อยู่ในคน (สำหรับชั้นMyView2ขวา: R.styleable.MyView2_myattr1ผิด: R.styleable.MyView_myattr1)
vigilancer

28

ดังที่ Priya Singhal ตอบแล้ว Android Studio ต้องการชื่อแอตทริบิวต์ทั่วไปเพื่อกำหนดไว้ในชื่อสไตล์ของตนเอง พวกเขาไม่สามารถอยู่ที่รากได้อีกต่อไป

อย่างไรก็ตามมีอีกสองสามสิ่งที่ควรทราบ (ซึ่งเป็นสาเหตุที่ฉันเพิ่มคำตอบด้วย):

  • สไตล์ทั่วไปไม่จำเป็นต้องตั้งชื่อให้เหมือนกับมุมมอง (ขอบคุณคำตอบนี้สำหรับการชี้ว่า)
  • คุณไม่จำเป็นต้องใช้การสืบทอดกับพาเรนต์

ตัวอย่าง

นี่คือสิ่งที่ฉันทำในโครงการเมื่อเร็ว ๆ นี้ที่มีมุมมองที่กำหนดเองสองแบบที่ทั้งสองใช้คุณลักษณะร่วมกัน ตราบใดที่มุมมองที่กำหนดเองยังคงมีชื่อสำหรับแอตทริบิวต์และไม่รวม a formatฉันยังสามารถเข้าถึงได้ตามปกติจากรหัส

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <!-- common attributes to all custom text based views -->

    <declare-styleable name="TextAttributes">
        <attr name="text" format="string"/>
        <attr name="textSize" format="dimension"/>
        <attr name="textColor" format="color"/>
        <attr name="gravity">
            <flag name="top" value="48" />
            <flag name="center" value="17" />
            <flag name="bottom" value="80" />
        </attr>
    </declare-styleable>

    <!-- custom text views -->

    <declare-styleable name="View1">
        <attr name="text"/>
        <attr name="textSize"/>
        <attr name="textColor"/>
        <attr name="gravity"/>
    </declare-styleable>

    <declare-styleable name="View2">
        <attr name="text"/>
        <attr name="textSize"/>
        <attr name="textColor"/>
        <attr name="gravity"/>
    </declare-styleable>

</resources>

ตัวอย่างที่คล่องตัว

ในความเป็นจริงฉันไม่จำเป็นต้องใส่แอตทริบิวต์ในชื่อที่กำหนดเอง ตราบใดที่ฉันกำหนด (ให้พวกเขาformat) สำหรับมุมมองที่กำหนดเองอย่างน้อยหนึ่งรายการฉันสามารถใช้พวกเขาได้ทุกที่ (ไม่มีformat) ดังนั้นวิธีนี้จึงใช้งานได้ (และดูสะอาดกว่า):

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="View1">
        <attr name="text" format="string"/>
        <attr name="textSize" format="dimension"/>
        <attr name="textColor" format="color"/>
        <attr name="gravity">
            <flag name="top" value="48" />
            <flag name="center" value="17" />
            <flag name="bottom" value="80" />
        </attr>
    </declare-styleable>

    <declare-styleable name="View2">
        <attr name="text"/>
        <attr name="textSize"/>
        <attr name="textColor"/>
        <attr name="gravity"/>
    </declare-styleable>

</resources>

อย่างไรก็ตามสำหรับโครงการขนาดใหญ่สิ่งนี้อาจทำให้เกิดความยุ่งเหยิงและการกำหนดที่ด้านบนในตำแหน่งเดียวอาจจะดีกว่า (ตามที่แนะนำไว้ที่นี่ )


เกิดอะไรขึ้นกับมรดก ฉันมีลำดับชั้นการดูแบบกำหนดเองที่มี styleables ที่เกี่ยวข้องไม่สะท้อนความสัมพันธ์นี้ซึ่งสามารถอนุมานได้ในคำจำกัดความของสไตล์ที่เกี่ยวข้องโดยการตั้งชื่อแบบแผนและรายการเฉพาะที่กำหนดไว้ในนั้น ฉันต้องการให้ชัดเจนกับparentแอตทริบิวต์ แต่ไม่เห็นโพสต์มากมายที่แนะนำให้ใช้
Samis

@samis ฉันไม่ได้ทำงานอยู่ในขณะนี้ parentแต่ผมไม่ทราบว่าผิดอะไรกับการใช้ ฉันคิดว่าฉันแค่บอกว่าไม่จำเป็น
Suragch

ไม่ต้องการฉันเพิ่งสร้างคลาสย่อยอื่นล้อมรอบแอตทริบิวต์เพิ่มเติมที่ฉันไม่ต้องการใส่ลงในคลาสพื้นฐาน ฉันแค่ใช้ความคิดเห็นและแบบแผนการตั้งชื่อเพื่อระบุการแยก
Samis

8

ขอบคุณลูอิสฉันมีปัญหาเดียวกันและวิธีแก้ปัญหาการสืบทอดของคุณทำให้ฉันได้รับคำแนะนำสำหรับการทำเหมือนด้านล่างและใช้งานได้ดีฉันเพิ่งประกาศคุณลักษณะทั่วไปที่ด้านบนและเขียนมันลงในเนื้อความของการประกาศสไตล์อีกครั้ง ฉันหวังว่ามันจะช่วยให้ใครบางคน

<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- common attributes -->
     <attr name="myattr1" format="string" />
     <attr name="myattr2" format="dimension" />

 <!-- also note "myBackgroundColor" belongs to child styleable"MyView1"-->
<declare-styleable name="MyView1" >
    <attr name="myattr1" />
    <attr name="myattr2" />
    <attr name="myBackgroundColor" format="color"/>
</declare-styleable>

<!-- same way here "myfonnt" belongs to child styelable "MyView2" -->
<declare-styleable name="MyView2" parent="MyView">
    <attr name="myattr1" />
    <attr name="myattr2" />
    <attr name="myfont" format="string"/>
    ...
</declare-styleable>


1

ในกรณีที่บางคนยังคงติดอยู่กับปัญหานี้หลังจากลองวิธีการแก้ปัญหาที่มีอยู่ ฉันติดอยู่กับเพิ่มsubtitleคุณสมบัติที่มีstringรูปแบบ

โซลูชันของฉันลบรูปแบบ

ก่อน:

<attr name="subtitle" format="string"/>

หลังจาก:

<attr name="subtitle"/>

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.