การเพิ่มสีแบบไดนามิกให้กับแอป

1. ก่อนเริ่มต้น

ในโค้ดแล็บนี้ คุณจะอัปเดตแอปเริ่มต้น ซึ่งเป็นแอปเครื่องคำนวณทิป เพื่อใช้ฟีเจอร์ใหม่ใน Material Design 3 ที่ช่วยให้สามารถกำหนดธีมอินเทอร์เฟซผู้ใช้ของแอปพลิเคชันแบบไดนามิกตามวอลเปเปอร์ของผู้ใช้ ด้านล่างนี้คือภาพหน้าจอ 2 ภาพของแอปพลิเคชันที่ใช้สีแบบไดนามิก นอกจากนี้ คุณยังจะได้ดูสถานการณ์เพิ่มเติมบางอย่างที่ช่วยให้คุณควบคุมวิธีใช้สีได้ด้วย

ข้อกำหนดเบื้องต้น

นักพัฒนาแอปควร

  • คุ้นเคยกับแนวคิดการกำหนดธีมพื้นฐานใน Android
  • คุ้นเคยกับการแก้ไขธีมของแอป

สิ่งที่คุณจะได้เรียนรู้

  • วิธีแยกความแตกต่างระหว่างคอมโพเนนต์ Material ที่มีอยู่กับธีม Material 3
  • วิธีอัปเดตธีมเป็น Material 3
  • วิธีสร้างธีมโดยใช้เครื่องมือของเราและนำไปใช้
  • ความสัมพันธ์ของแอตทริบิวต์ธีม

สิ่งที่คุณต้องมี

2. ภาพรวมแอปเริ่มต้น

แอป Tip Time เป็นแอปเครื่องคำนวณทิปที่มีตัวเลือกในการปรับแต่งทิป ซึ่งเป็นหนึ่งในตัวอย่างแอปจากหลักสูตรการฝึกอบรมข้อมูลพื้นฐานเกี่ยวกับ Android ใน Kotlin

59906a9f19d6b804.png

3. การอัปเดตทรัพยากร Dependency ของ Gradle

ก่อนที่เราจะอัปเดตธีมจริงและใช้สีแบบไดนามิก คุณต้องทำการเปลี่ยนแปลงบางอย่างในไฟล์ build.gradle สำหรับแอปพลิเคชันของคุณ

ในส่วนทรัพยากร Dependency ให้ตรวจสอบว่าไลบรารี Material เป็นเวอร์ชัน 1.5.0-alpha04 ขึ้นไป

dependencies {
    // ...
    implementation 'com.google.android.material:material:<version>'
}

ในส่วน Android ให้เปลี่ยน compileSdkVersion และ targetSdkVersion

ถึง 31 หรือหลังจากนั้น

android {
    compileSdkVersion 31
    // ...

    defaultConfig {
        // ...
        targetSdkVersion 31
    }
}

คำสั่งเหล่านี้ถือว่าแอปมีทรัพยากร Dependency ที่ค่อนข้างใหม่ สำหรับแอปที่ยังไม่ได้ใช้ Material หรือใช้เวอร์ชันที่เก่ากว่า โปรดดูวิธีการในเอกสารประกอบการเริ่มต้นใช้งานของคอมโพเนนต์ Material Design สำหรับ Android

ไม่ว่าคุณจะสร้างธีมไว้ที่ใด ให้เปลี่ยนการอ้างอิงของ Theme.MaterialComponents.* เป็น Theme.Material3.* บางสไตล์ยังไม่มีสไตล์ใหม่ในเนมสเปซ Material3 แต่คอมโพเนนต์ส่วนใหญ่จะยังคงรับช่วงสไตล์ใหม่เมื่ออัปเดตธีมหลักเป็น Theme.Material3.* เราจะเห็นด้านล่างว่าตอนนี้ปุ่มต่างๆ ใช้ธีมใหม่แบบโค้งมนแล้ว

ในไฟล์ธีมด้านล่าง สิ่งเดียวที่เปลี่ยนแปลงคือธีมหลัก เราจะแทนที่ธีมนี้ทั้งหมดในอีกสักครู่ แอตทริบิวต์สีบางอย่างเลิกใช้งานแล้ว และสไตล์ที่กำหนดเองบางอย่างที่เราสร้างขึ้นได้กลายเป็นมาตรฐานใน Material3 แล้ว แต่เราต้องการให้คุณมี

themes.xml

<style name="Theme.TipTime" parent="Theme.Material3.Light">
   <!-- Primary brand color. -->
   <item name="colorPrimary">@color/green</item>
   <item name="colorPrimaryVariant">@color/green_dark</item>
   <item name="colorOnPrimary">@color/white</item>
   <!-- Secondary brand color. -->
   <item name="colorSecondary">@color/blue</item>
   <item name="colorSecondaryVariant">@color/blue_dark</item>
   <item name="colorOnSecondary">@color/black</item>
   <!-- Status bar color. -->
   <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
   <!-- For text input fields -->
   <item name="textInputStyle">@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox</item>
   <!-- For radio buttons -->
   <item name="radioButtonStyle">@style/Widget.TipTime.CompoundButton.RadioButton</item>
   <!-- For switches -->
   <item name="switchStyle">@style/Widget.TipTime.CompoundButton.Switch</item>
</style>

f91e2acbac7cd469.png

4. ทำความเข้าใจการกำหนดธีมสีและบทบาทของสี

ระบบสี Material 3 ใช้แนวทางที่มีการจัดระเบียบเพื่อใช้สีกับ UI แอตทริบิวต์จำนวนหนึ่งจาก Theme.AppCompat ยังคงใช้งานอยู่ อย่างไรก็ตาม มีการเพิ่มแอตทริบิวต์เพิ่มเติมใน Theme.MaterialComponents.* และเพิ่มอีกใน Theme.Material3.* ดังนั้นคุณจึงควรตรวจสอบทุกหน้าจอของแอปเพื่อให้แน่ใจว่าไม่มีพร็อพเพอร์ตี้ที่ไม่ได้ใช้หลุดมาจากธีมฐาน

ทำความเข้าใจบทบาทของสี

ธีม Material 3 มีแอตทริบิวต์ที่เกี่ยวข้องกับสีมากกว่า 20 รายการ ในตอนแรกอาจดูน่ากลัว แต่จริงๆ แล้วมีสีหลักเพียงไม่กี่สีที่ใช้ร่วมกับบทบาทสีเดียวกัน 4-5 สีเพื่อสร้างสีอนุพันธ์

กลุ่มสีเหล่านั้น ได้แก่

  • Primary สีหลักของแอป
  • รอง สีรองของแอป
  • สีตติยภูมิ ซึ่งเป็นสีที่ 3 ที่เป็นสีเสริมของสีปฐมภูมิและสีทุติยภูมิ
  • ข้อผิดพลาด ใช้สำหรับข้อความและกล่องโต้ตอบแสดงข้อผิดพลาด
  • ฉากหลัง
  • Surface, SurfaceVariant, Surface Inverse

โดยมีบทบาทดังนี้สำหรับ Primary, Secondary, Tertiary และ Error

<สีพื้นฐาน>

สีพื้น

on<base color>

สีของไอคอนและข้อความที่ปรากฏบนสีพื้น

คอนเทนเนอร์ <สีพื้นฐาน>

ได้มาจากสีพื้นฐาน ใช้สำหรับปุ่ม กล่องโต้ตอบ ฯลฯ

on<base color>Container

สีของไอคอนและข้อความในคอนเทนเนอร์

ตัวอย่างเช่น ปุ่มลอยที่มีการจัดรูปแบบเริ่มต้นใน Material 3 จะใช้ Primary เป็นสีพื้นฐาน ดังนั้นจึงใช้ primaryContainer เป็นสีพื้นหลังของปุ่ม และใช้ onPrimaryContainer เป็นเนื้อหาของปุ่ม

เมื่อปรับแต่งธีมด้วยตนเอง คุณควรตรวจสอบอย่างน้อยว่าon<base color>แอตทริบิวต์สำหรับสีฐานทุกสีที่คุณเปลี่ยนยังคงอ่านได้

แนวทางปฏิบัติแนะนำคือการปรับบทบาททั้งหมดในกลุ่มสีพร้อมกันเพื่อให้แน่ใจว่าไม่มีสิ่งประดิษฐ์จากฐานผ่านไปยังแอป

โดยทั่วไปแล้ว สีพื้นหลังและสีฐานของ Surface จะมี 2 บทบาท ได้แก่ สีฐานเองและ on<base color> สำหรับไอคอนหรือข้อความที่ปรากฏบนสีฐาน

5. การสร้างธีม Material 3 ด้วย Material Theme Builder

Material Theme Builder ช่วยให้สร้างรูปแบบสีที่กำหนดเอง ใช้การส่งออกโค้ดในตัวเพื่อย้ายข้อมูลไปยังระบบสี M3 และใช้ประโยชน์จากสีแบบไดนามิกได้อย่างง่ายดาย ดูข้อมูลเพิ่มเติม material.io/material-theme-builder

ธีมแอป Tip Time มีหลายสไตล์สำหรับคอมโพเนนต์ แต่สไตล์ส่วนใหญ่เป็นค่าเริ่มต้นในธีม Material 3 สีหลัก 2 สีที่เราต้องกังวลคือสีหลักและสีรอง

ซึ่งตรงกับสีหลักสีเขียว (#1B5E20) และสีรองสีน้ำเงิน (#0288D1)

คุณสามารถป้อนสีเหล่านั้นลงใน Material Theme Builder และส่งออกธีมแบบเต็มได้ (สมมติว่ามีลิงก์ไปยังภาพรวมแบบเต็มที่อื่น)

โปรดทราบว่าสีที่คุณป้อนอาจมีการปรับโทนเพื่อให้เข้ากับอัลกอริทึมการสร้างสี และเพื่อให้มั่นใจว่าสีจะเสริมกันและอ่านได้

ด้านล่างนี้คือชุดย่อยของค่าที่สร้างขึ้นเมื่อคุณป้อนสีที่กำหนดเอง

7f6c5a33f5233811.png

6. การทำงานกับไฟล์ส่งออกของ Material Theme Builder

ไฟล์เก็บถาวรที่ส่งออกจะมีไดเรกทอรี values และ values-night/ พร้อมไฟล์ themes.xml ของตัวเอง ซึ่งสอดคล้องกับธีมสว่างและธีมมืด สีทั้งหมดกำหนดไว้ใน values/colors.xml

f66a64db2989a260.png

คุณสามารถคัดลอกไฟล์ได้ตามเดิม แต่จะต้องเปลี่ยนชื่อธีมใน AndroidManifest.xml หรือในไฟล์ธีมให้ตรงกัน ชื่อเริ่มต้นจากเครื่องมือคือ AppTheme

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

38a50ada47fd5ea4.png

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="com.example.tiptime">

   <application ...>
       <activity android:name=".MainActivity"
           android:exported="true">
           <intent-filter>
               <action android:name="android.intent.action.MAIN" />

               <category android:name="android.intent.category.LAUNCHER" />
           </intent-filter>
       </activity>
   </application>

</manifest>

7. การเพิ่มสีแบบเปลี่ยนอัตโนมัติ

เมื่อใช้ธีม Material 3 ที่เหมาะสม เราจะทำให้ UI เป็นแบบไดนามิกได้ด้วยการเพิ่มเล็กๆ น้อยๆ

API สีแบบไดนามิกช่วยให้คุณใช้สีแบบไดนามิกกับกิจกรรมทั้งหมดได้

ในแอป กิจกรรมแต่ละรายการ หรือไปยัง View หรือ Fragment แต่ละรายการ สำหรับ

เราจะใช้สีไดนามิกทั่วโลก

สร้างไฟล์คลาสแอปพลิเคชัน

class TipTimeApplication: Application() {
    override fun onCreate() {
        // Apply dynamic color
        DynamicColors.applyToActivitiesIfAvailable(this)
    }
}

เราต้องอ้างอิงไฟล์ที่สร้างขึ้นใหม่นี้ใน Android Manifest ดังนี้

AndroidManifest.xml

< application android name=".TipTimeApplication
<!--- Other existing attributes –>

</application >

ในระบบ Android 12 ขึ้นไป ระบบจะตรวจสอบวอลเปเปอร์ของผู้ใช้สำหรับรูปแบบเริ่มต้นเพื่อสร้างจานสีโทนต่างๆ ระบบจะใช้ค่าจากจานสีเหล่านี้เพื่อสร้าง ThemeOverlay

คลาส DynamicColors จะลงทะเบียน ActivityLifecycleCallbacks ที่สกัดกั้นใน ActivityPreCreated เพื่อใช้การวางซ้อนธีมแบบไดนามิกที่ระบบสร้างขึ้นหรือธีมที่คุณระบุ

eba71f96f4ba9cdf.png

8. การใช้การวางซ้อนธีมที่กำหนดเอง

เครื่องมือของเราสามารถส่งออกการซ้อนทับธีมได้ แต่คุณก็สร้างด้วยตนเองได้เช่นกันหากจะลบล้างแอตทริบิวต์จำนวนเล็กน้อย

การวางซ้อนธีมมีไว้เพื่อใช้ร่วมกับธีมอื่น และจะให้เฉพาะค่าที่จะเปลี่ยนแปลงบนธีมฐานเท่านั้น

สมมติว่าด้วยเหตุผลบางอย่าง เช่น การสร้างแบรนด์ เราต้องการให้โทนสีหลักเป็นเฉดสีแดง เราทำได้ด้วยไฟล์และแอตทริบิวต์ต่อไปนี้

colors.xml

<resources>
    <color name="overlay_light_primary">#9C4146</color>
    <color name="overlay_light_onPrimary">#FFFFFF</color> 
    <color name= "overlay_light_primaryContainer">#FFDADB</color>
    <color name="overlay_light_onPrimaryContainer">#400008</color>
</resources >

themes_overlays.xml

<style name="AppTheme.Overlay" parent="ThemeOverlay.Material3.DynamicColors.Light">
    <item name="colorPrimary">@color/overlay_light_primary</item>
    <item name="colorOnPrimary">@color/overlay_light_onPrimary</item> 
    <item name="colorPrimaryContainer">@color/overlay_light_primaryContainer</item> 
    <item name="colorOnPrimaryContainer">@color/overlay_light_onPrimaryContainer<item>
</style>

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

ThemeOverlay.Material3.Light

ThemeOverlay.Material3.Dark

ThemeOverlay.Material3.DayNight ThemeOverlay.Material3.DynamicColors.Dark

ThemeOverlay.Material3.DynamicColors.DayNight

หากต้องการใช้การวางซ้อนธีมนี้แทนค่าเริ่มต้นของ Material ให้เปลี่ยนการเรียกใช้เป็น DynamicColors.applyToActivitiesIfAvailable ดังนี้

DynamicColors.applyToActivitiesIfAvailable(this, R.style.AppTheme_Overlay)

d87020776782036f.png

9. การเพิ่มสีแบบไดนามิกลงในแอตทริบิวต์ที่กำหนดเอง

ที่ผ่านมาเราได้ลบล้างพร็อพเพอร์ตี้ที่มีอยู่ในธีม Material 3 อยู่แล้ว อีกกรณีหนึ่งที่อาจเกิดขึ้นในสีแบบไดนามิกคือเราอาจมีแอตทริบิวต์ที่กำหนดเองอย่างน้อย 1 รายการที่ต้องจัดสรร

เมื่อแอปเลือกใช้สีแบบไดนามิก แอปจะมีสิทธิ์เข้าถึงจานสีโทน 5 จาน ได้แก่ จานสีเฉพาะจุด 3 จานและจานสีที่เป็นกลาง 2 จาน โดยมีบทบาทโดยประมาณดังนี้

system_accent1

เฉดสีหลัก

system_accent2

โทนสีรอง

system_accent3

โทนสีขั้นที่ 3

system_neutral1

พื้นหลังและพื้นผิวที่เป็นกลาง

system_neutral2

พื้นผิวและเส้นขอบที่เป็นกลาง

แต่ละจานสีจะมีระดับโทนสีตั้งแต่สีขาว

เป็นสีดำ: 0, 10, 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000

เมื่อออกแบบ UI สำหรับสีแบบไดนามิก คุณควรพิจารณาถึงความสัมพันธ์ของโทนสีและความสว่างของคอมโพเนนต์นั้นกับคอมโพเนนต์อื่นๆ ในระบบการออกแบบมากกว่าการพิจารณาสีที่เฉพาะเจาะจง

สมมติว่าคุณต้องการให้ไอคอนใช้ธีมโดยใช้จานสีรองและเพิ่มแอตทริบิวต์เพื่อปรับสีไอคอนด้วยรายการต่อไปนี้ใน attrs.xml

attrs.xml

<resources>
    <attr name="iconColor" format="color" />
</resources>

การวางซ้อนธีมอาจมีลักษณะดังนี้

<style name="AppTheme.Overlay" parent="ThemeOverlay.Material3.DynamicColors.DayNight"> 
<item name="iconColor">@android:color/system_accent2_600</item>
</style>

เมื่อคุณติดตั้งแอปอีกครั้งและเปลี่ยนวอลเปเปอร์ แอปจะเลือกใช้ชุดสีรองนั้น

11ef0035702640d9.png

264b2c2e74c5f574.png

จานสีเหล่านี้ใช้ได้กับ Android 12 (API 31) โดยเฉพาะ ดังนั้นคุณจะต้องวางไฟล์ที่เกี่ยวข้องในโฟลเดอร์ที่มีคำต่อท้าย -v31 เว้นแต่แอปของคุณจะมี SDK ขั้นต่ำที่ตั้งค่าเป็น 31 ขึ้นไป

10. สรุป

ในโค้ดแล็บนี้ คุณได้ทำสิ่งต่อไปนี้

  • เพิ่มทรัพยากร Dependency เพื่ออัปเกรดธีมเป็น Material 3
  • ทำความเข้าใจกลุ่มสีและบทบาทใหม่
  • ทําความเข้าใจวิธีย้ายข้อมูลจากธีมแบบคงที่ไปยังสีแบบเปลี่ยนอัตโนมัติ
  • ทำความเข้าใจวิธีใช้การวางซ้อนธีมและใช้สีแบบไดนามิกสำหรับแอตทริบิวต์ธีมที่กำหนดเอง