Android Resource เป็นหนึ่งในพื้นฐานของการพัฒนาแอนดรอยด์ที่ออกแบบมาให้อยู่ในรูปของ XML โดยหนึ่งในนั้นจะมีสิ่งที่เรียกว่า Style Resource ซึ่งเป็น Resource ที่มีประโยชน์มากๆในเวลาที่นักพัฒนาต้องทำสร้าง UI ใน Layout Resource

Style เป็น Resource ที่ใช้กำหนด Properties ต่างๆของ View ให้อยู่ในรูปที่นำไปใช้งานได้ง่าย แทนการกำหนด View Properties ลงใน Layout Resource โดยตรง

Style Resource ก็เปรียบเสมือน CSS สำหรับสาย Web นั่นเอง

ประโยชน์ของ Style Resource

สำหรับแอปที่มีขนาดใหญ่ ย่อมเลี่ยงไม่ได้ที่จะต้องมี Layout Resource เป็นจำนวนเยอะมากตามความสามารถที่มีในแอป ซึ่งจะมาพร้อมกับ Design System สำหรับแอปนั้นๆเพื่อให้การออกแบบ UI ของแอปนั้นเป็นไปในทิศทางเดียวกัน และสามารถนำสิ่งที่มีอยู่แล้ว Reuseable หรือนำมาใช้ซ้ำๆได้ง่ายขึ้น ลดระยะเวลาที่ไม่จำเป็นออกไปเพื่อให้การพัฒนาฟีเจอร์ใหม่ๆทำได้ง่ายขึ้นและไวขึ้น

ซึ่งรวมไปถึงการสร้าง UI บนแอนดรอยด์ด้วยเช่นกัน จึงทำให้ในขั้นตอนการสร้าง UI จึงมีบางอย่างที่ควรจะ Reuseable ได้ และนั่นก็คือ View Properties นั่นเอง

เมื่อ Properties ต่างๆของ View สามารถจัดกลุ่ม Component ตามที่กำหนดไว้ใน Typography ของ Design System ได้ จะดีกว่ามั้ยถ้าเตรียมค่าเหล่านี้ให้พร้อมไว้ใน Style Resource แล้วนำ Style นั้นๆไปใช้งานได้เลย

และเวลามีการแก้ไข UI ในภายหลัง ก็สามารถแก้ไขได้ง่าย เช่น ต้องการเปลี่ยนขนาดข้อความที่เป็นแบบ Body ทั้งหมดจาก 14sp เป็น 16sp ก็สามารถเปลี่ยนค่าใน Style Resource ได้เลย

นอกจากนี้ยังสามารถใช้งานร่วมกับ Android Resource ตัวอื่นๆได้อีกด้วย ไม่ว่าจะเป็น Color Resource หรือ Dimension Resource ก็ตาม

การสร้าง Style Resource และเรียกใช้งาน

จริงๆแล้ว Style Resource ก็ถือว่าเป็น Value Resource อย่างหนึ่งเช่นกัน ดังนั้นการสร้าง Style Resource จะสร้างเป็นไฟล์ XML ชื่ออะไรก็ได้ไว้ใน values ก็พอ

ส่วนใหญ่จะนิยมตั้งชื่อว่า styles.xml กัน และโดยปกติจะมีไฟล์ของ Style Resource สร้างเตรียมไว้ให้อยู่แล้วตั้งแต่แรก

Project Template ล่าสุดใน Android Studio ได้เปลี่ยนชื่อไฟล์จาก styles.xml เป็น themes.xml แทน

ในการสร้าง Style ใดๆก็ตามจะใช้ <style> เป็นตัวกำหนดเสมอ โดยจะอยู่ใน <resources> เหมือนกับ Value Resource ตัวอื่นๆ ยกตัวอย่างเช่น

<resources>
    <style name="Heading">
        <!-- Add view attribute here -->
    </style>
</resources>

โดยข้างใน <style> ให้กำหนด View Properties ที่ต้องการเข้าไปให้เรียบร้อย

<resources>
    <style name="Heading">
        <item name="android:textSize">14sp</item>
        <item name="android:textColor">#374257</item>
        <item name="android:fontFamily">@noto_sans</item>
        <item name="android:textStyle">bold</item>
    </style>
    <style name="Body">
        <item name="android:textSize">14sp</item>
        <item name="android:textColor">#374257</item>
        <item name="android:fontFamily">@noto_sans</item>
        <item name="android:textStyle">bold</item>
    </style>
</resources>

จะเห็นว่าค่าต่างๆที่กำหนดอยู่ข้างใน <style> จะใช้เป็น <item> เสมอ ส่วน Attribute ที่ชื่อว่า name ก็จะเป็น View Properies ที่ต้องการกำหนดนั่นเอง

ตอนนำไปใช้งานก็จะกำหนดผ่าน Attribute ที่ชื่อว่า style ได้เลย

<TextView
    ... 
    style="@style/Heading" />

จะเห็นว่าการใช้ Style Resource นั้นจะช่วยลดจำนวนบรรทัดของ XML ที่จะต้องกำหนดใน Layout Resource ให้น้อยลงไปเยอะมาก โดยขึ้นอยู่กับจำนวน Properties ที่จะต้องกำหนดใน View นั้นๆ

Inheritance

อีกอย่างที่เจ้าของบล็อกชอบใน Style Resource มากๆ นั่นก็คือคุณสมบัติ Inheritance ที่เหมือนกับ CSS

ยกตัวอย่างเช่น เจ้าของบล็อกต้องการสร้าง Style สำหรับข้อความที่มีสีแตกต่างกัน

<style name="Heading">
    <item name="android:textSize">@dimen/heading_text_size</item>
    <item name="android:textColor">@color/black</item>
</style>

<style name="Heading.Gray">
    <item name="android:textColor">@color/gray</item>
</style>

<style name="Heading.White">
    <item name="android:textColor">@color/white</item> 
</style>

<style name="Heading.Red">
    <item name="android:textColor">@color/red</item>
</style>

<style name="Heading.Blue">
    <item name="android:textColor">@color/blue</item>
</style>

จะเห็นว่านักพัฒนาสามารถสร้าง Style ที่ชื่อว่า Heading ขึ้นมาโดยกำหนดขนาดและสีของตัวหนังสือ จากนั้นก็สร้าง Style ตัวอื่นๆที่กำหนดแค่สีของตัวหนังสือเท่านั้น เพราะ Inheritance ใน Style Style นั้นสามารถทำได้ง่ายๆด้วยการสร้าง Style ที่ใช้ชื่อแบบเดิมแต่มี Suffix ต่อท้ายที่คั่นด้วย .

เวลาเรียกใช้งานใน Layout Resource ก็จะขึ้น Code Completion ให้เลือกแบบนี้

ในกรณีที่ต้องการตั้งชื่อแตกต่างไปจากเดิมโดยสิ้นเชิง ก็สามารถกำหนดชื่อของ Style ได้ตามใจชอบแล้วใส่ parent พร้อมกับกำหนด Style ที่ต้องการได้เลย

<style name="Body">
    <!-- Style for TextView -->
</style>

<style name="Button" parent="Body">
    <!-- Style for Button -->
</style>

เพียงเท่านี้ Button ก็จะดึง Attribute ทั้งหมดของ Body แล้วนักพัฒนาก็สามารถกำหนด Attribute อื่นๆเพิ่มเข้าไปใน Button ได้เลย

กำหนด Style ในระดับ Application หรือ Activity ก็ได้นะ

จากตัวอย่างก่อนหน้า เจ้าของบล็อกกำหนด Style ลงใน View โดยตรง ซึ่งจะมีผลเฉพาะ View ที่ถูกกำหนดค่าลงไป แต่ถ้าอยากให้ทั้งแอปใช้ Style ที่เหมือนกันทั้งหมดก็สามารถกำหนด Attribute ที่ชื่อว่า android:theme ไว้ใน <application> ของ Android Manifest

<!-- AndroidManifest.xml -->
<manifest>
    <application
        ...
        android:theme="@style/Theme.Palette">
        <!-- ... -->
    </application>
</manifest>

เวลาที่สร้างโปรเจคขึ้นมาใหม่ จะมีการสร้าง Style เพื่อใช้กำหนดไว้ใน <application> ให้โดยทันที ถ้าอ้างอิงจาก Project Template ล่าสุด ก็จะใช้ Style ชื่อว่า Theme.Palette

และถ้าอยากกำหนดเฉพาะบาง Activity ก็สามารถทำได้เช่นกัน

<!-- AndroidManifest.xml -->
<manifest>
    <application>
        <activity
        	...
            android:theme="@style/Theme.FullScreen" />
    </application>
</manifest>

ซึ่งจะสะดวกมากๆในเวลาที่นักพัฒนาต้องการแยก Style สำหรับ Activity บางตัว

ถ้ากำหนดไว้ทั้งใน <application> และ <activity> ก็จะใช้ค่าที่กำหนดไว้ใน <activity>  เป็นหลัก

สิ่งที่ควรรู้เกี่ยวกับ Style Resource

Inheritance ด้วยชื่อ Style ไม่สามารถใช้กับ System Style ได้

ถ้าสร้าง Style จาก 3rd Party Library อีกทีหนึ่ง สามารถใช้วิธีกำหนด Suffix ต่อท้ายชื่อเดิมหรือกำหนดผ่าน parent ก็ได้

แต่ถ้าเป็น System Style ที่มีอยู่แล้วในระบบแอนดรอยด์ จะต้องทำใช้ parent เท่านั้น

การกำหนดค่าสำหรับ Custom Attribute

ถ้าเป็น System Attribute จะมี android: นำหน้าเสมอ แต่ถ้าเป็น Custom Attribute ไม่จำเป็นต้องใส่ Prefix สามารถกำหนดด้วยชื่อ Attribute นั้นๆได้เลย

<!-- System Attribute -->
<item name="android:textSize">14sp</item>

<!-- Custom Attribute -->
<item name="cpb_cornerRadius">16dp</item>

ใช้ร่วมกับ Configuration Qualifier ได้เหมือนกับ Android Resource ตัวอื่นๆ

นักพัฒนาสามารถแยก Style Resource ตาม Configuration Qualifier ได้ และมักจะนิยมใช้ใน Style Resource ในการทำให้แอปรองรับ Light Theme และ Dark Theme โดยแยกด้วย values และ values-night

res
  +-- values
  |     \-- themes.xml
  \-- values-night
        \-- themes.xml

หรือ View Attribute บางตัวที่รองรับเฉพาะบาง API Level ก็สามารถสร้าง Style โดยแบ่งออกเป็นหลายๆ API Level ก็ได้ เพื่อให้ Style นั้นๆรองรับกับ View Attribute เมื่อผู้ใช้เปิดใช้งานบนเวอร์ชันที่รองรับ

res
  +-- values
  |     \-- themes.xml
  +-- values-v21
  |     \-- themes.xml
  \-- values-v26
        \-- themes.xml

สรุป

Style Resource เป็นคุณสมบัติอย่างหนึ่งของแอนดรอยด์ที่จะช่วยให้การสร้าง UI บน Layout Resource สะดวกขึ้น ลดการกำหนด Attribute ที่ซ้ำซ้อนออกไปให้เหลือแค่เพียง Style ที่สามารถกำหนดเป็นชื่อที่กระชับและสื่อความเข้าใจได้ง่ายกว่า ซึ่งจะมีประโยชน์มากๆโดยเฉพาะการพัฒนาแอปร่วมกับคนอื่นๆในทีม

และสุดท้ายขอฝากไว้แค่ว่า “ใช้เถอะครับ แล้วชีวิตจะไม่ลำบาก”