Style and Theme — เพราะชีวิตต้องมีสไตล์
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 ที่สามารถกำหนดเป็นชื่อที่กระชับและสื่อความเข้าใจได้ง่ายกว่า ซึ่งจะมีประโยชน์มากๆโดยเฉพาะการพัฒนาแอปร่วมกับคนอื่นๆในทีม
และสุดท้ายขอฝากไว้แค่ว่า “ใช้เถอะครับ แล้วชีวิตจะไม่ลำบาก”