1. ก่อนเริ่มต้น
Relay คือชุดเครื่องมือที่ช่วยให้ทีมออกแบบคอมโพเนนต์ UI ใน Figma และใช้ในโปรเจ็กต์ Jetpack Compose ได้โดยตรง จึงไม่ต้องเสียเวลาไปกับข้อกำหนดการออกแบบและรอบการประกันคุณภาพ ซึ่งช่วยให้ทีมแสดง UI ที่ยอดเยี่ยมของ Android ได้อย่างรวดเร็ว
ใน Codelab นี้ คุณจะได้เรียนรู้วิธีผสานรวมแพ็กเกจ Relay UI ในกระบวนการพัฒนา Compose ของคุณ โดยจะเน้นที่เทคนิคการผนวกรวม ไม่ใช่ขั้นตอนการทำงานต้นทางถึงปลายทาง หากต้องการเรียนรู้เกี่ยวกับเวิร์กโฟลว์ทั่วไปสำหรับ Relay โปรดดูบทแนะนำพื้นฐานของ Relay
ข้อกำหนดเบื้องต้น
- ประสบการณ์การใช้งานขั้นพื้นฐานกับการเขียน หากยังไม่ได้ดำเนินการ ให้ทำ Codelab ของพื้นฐาน Jetpack Compose ให้เสร็จสมบูรณ์
- มีประสบการณ์ในการใช้ไวยากรณ์ Kotlin
สิ่งที่คุณจะได้เรียนรู้
- วิธีนำเข้าแพ็กเกจ UI
- วิธีผสานรวมแพ็กเกจ UI เข้ากับการนำทางและสถาปัตยกรรมข้อมูล
- วิธีรวมแพ็กเกจ UI ด้วยตรรกะตัวควบคุม
- วิธีแมปรูปแบบ Figma กับธีม Compose
- วิธีแทนที่แพ็กเกจ UI ด้วย Composable ที่มีอยู่ในโค้ดที่สร้างขึ้น
สิ่งที่คุณจะสร้าง
- การออกแบบแอปที่สมจริงโดยอิงตามแพ็กเกจ Relay ที่นักออกแบบให้ไว้ แอปนี้ชื่อว่า Reflect ซึ่งเป็นแอปติดตามประจำวันที่ส่งเสริมการฝึกสติและนิสัยที่ดี โดยมีคอลเล็กชันเครื่องมือติดตามหลายประเภทและ UI สำหรับเพิ่มและจัดการ แอปมีลักษณะเหมือนรูปภาพต่อไปนี้:
สิ่งที่คุณต้องมี
- Android Studio Electric Eel ขึ้นไป
- บัญชี Figma ฟรีและโทเค็นเพื่อการเข้าถึงส่วนตัว
2. ตั้งค่า
รับโค้ด
หากต้องการรับโค้ดสำหรับ Codelab นี้ ให้ทำอย่างใดอย่างหนึ่งต่อไปนี้
- โคลนที่เก็บ
relay-codelabs
จาก GitHub ดังนี้
$ git clone https://github.com/googlecodelabs/relay-codelabs
- ไปที่ที่เก็บ
relay-codelabs
บน GitHub เลือก Branch ที่ต้องการ แล้วคลิกโค้ด > ดาวน์โหลดไฟล์ ZIP แล้วแตกไฟล์ ZIP ที่ดาวน์โหลด
ในทั้ง 2 กรณี Branch main
จะมีโค้ดเริ่มต้นและ Branch ของ end
จะมีโค้ดโซลูชัน
ติดตั้งปลั๊กอิน Relay สำหรับ Android Studio
หากคุณยังไม่มีปลั๊กอิน Relay สำหรับ Android Studio ให้ทำตามขั้นตอนต่อไปนี้
- ใน Android Studio ให้คลิกการตั้งค่า > ปลั๊กอิน
- ป้อน
Relay for Android Studio
ในกล่องข้อความ - คลิกติดตั้งตรงส่วนขยายที่ปรากฏในผลการค้นหา
- หากเห็นกล่องโต้ตอบหมายเหตุความเป็นส่วนตัวของปลั๊กอินของบุคคลที่สาม ให้คลิกยอมรับ
- คลิก OK > รีสตาร์ท
- หากคุณเห็นกล่องโต้ตอบยืนยันการออก ให้คลิกออก
เชื่อมต่อ Android Studio กับ Figma
Relay เรียกแพ็กเกจ UI ด้วย Figma API หากต้องการใช้งาน คุณจะต้องมีบัญชี Figma แบบฟรีและโทเค็นเพื่อการเข้าถึงส่วนตัว จึงเป็นเหตุผลว่าทำไมสิ่งเหล่านี้จึงแสดงอยู่ในส่วนสิ่งที่คุณต้องใช้
หากยังไม่ได้เชื่อมต่อ Android Studio กับ Figma ให้ทำตามขั้นตอนต่อไปนี้
- ในบัญชี Figma ให้คลิกไอคอนโปรไฟล์ที่ด้านบนของหน้า แล้วเลือกการตั้งค่า
- ในส่วนโทเค็นเพื่อการเข้าถึงส่วนบุคคล ให้ป้อนคำอธิบายโทเค็นในกล่องข้อความ แล้วกด
Enter
(หรือreturn
ใน macOS) ระบบจะสร้างโทเค็น - คลิกคัดลอกโทเค็นนี้
- ใน Android Studio ให้เลือกเครื่องมือ > การตั้งค่าการส่งต่อ กล่องโต้ตอบการตั้งค่าการส่งต่อจะปรากฏขึ้น
- ในช่องข้อความโทเค็นเพื่อการเข้าถึง Figma ให้วางโทเค็นเพื่อการเข้าถึงแล้วคลิกตกลง ตั้งค่าสภาพแวดล้อมแล้ว
3. ตรวจสอบการออกแบบของแอป
สำหรับแอป Reflect เราทำงานร่วมกับนักออกแบบเพื่อช่วยกำหนดสี การออกแบบตัวอักษร เลย์เอาต์ และลักษณะการทำงานของแอป เราสร้างการออกแบบเหล่านี้ตามแบบแผน 3 แบบของดีไซน์ Material เพื่อให้แอปทำงานกับองค์ประกอบและธีมของ Material ได้อย่างราบรื่น
ดูหน้าจอหลัก
หน้าจอหลักจะแสดงรายการติดตามที่ผู้ใช้กำหนด นอกจากนี้ยังช่วยให้สามารถเปลี่ยนแปลงวันที่ทำกิจกรรมและสร้างเครื่องมือติดตามอื่นๆ ได้ด้วย
ใน Figma ผู้ออกแบบของเราแบ่งหน้าจอนี้ออกเป็นหลายคอมโพเนนต์ กำหนด API และจัดแพ็กเกจเข้าด้วยกันด้วยปลั๊กอิน Relay for Figma หลังจากรวมคอมโพเนนต์เหล่านี้แล้ว คุณจะนำเข้าไปยังโปรเจ็กต์ Android Studio ได้
ตรวจสอบหน้าจอเพิ่ม/แก้ไข
หน้าจอเพิ่ม/แก้ไขช่วยให้ผู้ใช้เพิ่มหรือแก้ไขอุปกรณ์ติดตามได้ แบบฟอร์มที่แสดงจะแตกต่างกันเล็กน้อยตามประเภทเครื่องมือติดตาม
ในทำนองเดียวกัน หน้าจอนี้จะแบ่งออกเป็นคอมโพเนนต์แพ็กเกจหลายรายการ
ตรวจสอบธีม
สีและตัวอักษรสำหรับการออกแบบนี้จะใช้เป็นสไตล์ Figma ตามชื่อโทเค็นของ Material Design 3 วิธีนี้จะช่วยให้ทำงานร่วมกับธีม Compose และคอมโพเนนต์ Material ได้ดียิ่งขึ้น
4. นำเข้าแพ็กเกจ UI
รับลิงก์ไปยังแหล่งที่มาของ Figma
คุณต้องอัปโหลดแหล่งที่มาของการออกแบบไปยัง Figma ก่อน จึงจะนำเข้าแพ็กเกจ UI ไปยังโปรเจ็กต์ได้
หากต้องการรับลิงก์ไปยังแหล่งที่มาของ Figma ให้ทำตามขั้นตอนต่อไปนี้
- ใน Figma ให้คลิกนำเข้าไฟล์ แล้วเลือกไฟล์
ReflectDesign.fig
ที่พบในโฟลเดอร์โปรเจ็กต์CompleteAppCodelab
- คลิกขวาที่ไฟล์แล้วเลือกคัดลอกลิงก์ คุณจำเป็นต้องใช้ในส่วนถัดไป
นำเข้าแพ็กเกจ UI ไปยังโปรเจ็กต์
- ใน Android Studio ให้เปิดโปรเจ็กต์
./CompleteAppCodelab
- คลิกไฟล์ > ใหม่ > นำเข้าแพ็กเกจ UI กล่องโต้ตอบนำเข้าแพ็กเกจ UI จะปรากฏขึ้น
- ในกล่องข้อความ Figma source URL ให้วาง URL ที่คุณคัดลอกไว้ในส่วนก่อนหน้า
- ในกล่องข้อความธีมแอป ให้ป้อน
com.google.relay.example.reflect.ui.theme.ReflectTheme
วิธีนี้ช่วยให้มั่นใจว่าตัวอย่างที่สร้างขึ้นใช้ธีมที่กำหนดเอง - คลิกถัดไป คุณจะเห็นตัวอย่างแพ็กเกจ UI ของไฟล์
- คลิกสร้าง ระบบจะนำเข้าแพ็กเกจไปยังโปรเจ็กต์
- ไปที่แท็บโปรเจ็กต์ แล้วคลิก
ลูกศรขยายข้างโฟลเดอร์
ui-packages
- คลิก
ลูกศรขยายข้างโฟลเดอร์แพ็กเกจ แล้วสังเกตว่ามีไฟล์ต้นฉบับ
JSON
และทรัพยากร Dependency อยู่ - เปิดไฟล์ต้นฉบับ
JSON
โมดูล Relay จะแสดงตัวอย่างของแพ็กเกจและ API ของแพ็กเกจ
สร้างโค้ด
- ที่ด้านบนของ Android Studio ให้คลิก
สร้างโปรเจ็กต์ ระบบจะเพิ่มรหัสที่สร้างขึ้นสำหรับแต่ละแพ็กเกจลงในโฟลเดอร์
java/com.google.relay.example.reflect
Composable ที่สร้างขึ้นมีข้อมูลเลย์เอาต์และการจัดรูปแบบทั้งหมดจากการออกแบบ Figma - เปิดไฟล์
com/google/relay/example/reflect/range/Range.kt
- โปรดทราบว่าระบบจะสร้างตัวอย่างการเขียนสำหรับรูปแบบคอมโพเนนต์แต่ละรูปแบบ หากจำเป็น ให้คลิกแยกเพื่อให้เห็นโค้ดและหน้าต่างแสดงตัวอย่างอยู่ติดกัน
5. ผสานรวมคอมโพเนนต์
ในส่วนนี้ คุณจะได้รายละเอียดเกี่ยวกับโค้ดที่สร้างขึ้นสำหรับตัวติดตามสวิตช์
- ใน Android Studio ให้เปิดไฟล์
com/google/relay/example/reflect/switch/Switch.kt
Switch.kt (สร้างแล้ว)
/**
* This composable was generated from the UI Package 'switch'.
* Generated code; don't edit directly.
*/
@Composable
fun Switch(
modifier: Modifier = Modifier,
isChecked: Boolean = false,
emoji: String = "",
title: String = ""
) {
TopLevel(modifier = modifier) {
if (isChecked) {
ActiveOverlay(modifier = Modifier.rowWeight(1.0f).columnWeight(1.0f)) {}
}
TopLevelSynth(modifier = Modifier.rowWeight(1.0f)) {
Label(modifier = Modifier.rowWeight(1.0f)) {
Emoji(emoji = emoji)
Title(
title = title,
modifier = Modifier.rowWeight(1.0f)
)
}
Checkmark {
if (isChecked) {
Icon()
}
}
}
}
}
- โปรดสังเกตสิ่งต่อไปนี้
- ระบบจะสร้างเลย์เอาต์และการจัดรูปแบบทั้งหมดจากการออกแบบ Figma
- องค์ประกอบย่อยจะแบ่งออกเป็น Composable แยกกัน
- ระบบจะสร้างหน้าตัวอย่างที่ประกอบกันได้สำหรับการออกแบบรูปแบบต่างๆ ทั้งหมด
- สีและรูปแบบตัวอักษรจะฮาร์ดโค้ดไว้ คุณแก้ไขปัญหานี้ในภายหลัง
ใส่อุปกรณ์ติดตาม
- ใน Android Studio ให้เปิดไฟล์
java/com/google/relay/example/reflect/ui/components/TrackerControl.kt
ไฟล์นี้ให้ข้อมูลและตรรกะการโต้ตอบต่อเครื่องมือติดตามพฤติกรรม - สร้างและเรียกใช้แอปในโปรแกรมจำลอง ปัจจุบันคอมโพเนนต์นี้จะส่งออกข้อมูลดิบจากโมเดลตัวติดตาม
- นำเข้าแพ็กเกจ
com.google.relay.example.reflect.switch.Switch
ลงในไฟล์ - แทนที่
Text(text = trackerData.tracker.toString())
ด้วยบล็อกwhen
ที่หมุนในช่องtrackerData.tracker.type
- ในเนื้อหาของการบล็อก
when
ให้เรียกฟังก์ชันSwitch()
Composable
เมื่อประเภทเป็นTrackerType.BOOLEAN
โค้ดของคุณควรมีลักษณะดังนี้
TrackerControl.kt
// TODO: replace with Relay tracker components
when (trackerData.tracker.type) {
TrackerType.BOOLEAN ->
Switch(
title = trackerData.tracker.name,
emoji = trackerData.tracker.emoji
)
else ->
Text(trackerData.tracker.toString())
}
- สร้างโปรเจ็กต์อีกครั้ง ตอนนี้หน้าแรกแสดงตัวติดตามสวิตช์ได้อย่างถูกต้องตามที่ออกแบบด้วยข้อมูลแบบเรียลไทม์
6. เพิ่มสถานะและการโต้ตอบ
แพ็กเกจ UI เป็นแบบไม่เก็บสถานะ สิ่งที่แสดงผลจะเป็นผลลัพธ์แบบง่ายของพารามิเตอร์ที่ส่งผ่าน แต่แอปจริงต้องมีการโต้ตอบและสถานะ เครื่องจัดการการโต้ตอบอาจส่งผ่านไปยัง Composable ที่สร้างขึ้นเช่นเดียวกับพารามิเตอร์อื่นๆ แต่คุณจะเก็บสถานะที่เครื่องจัดการเหล่านั้นจัดการไว้ที่ใด คุณจะหลีกเลี่ยงการส่งตัวแฮนเดิลเดียวกันไปยังอินสแตนซ์ทุกรายการได้อย่างไร คุณจะนำองค์ประกอบของแพ็กเกจมาประกอบกันเป็น Composable ที่นำกลับมาใช้ใหม่ได้อย่างไร สำหรับกรณีเหล่านี้ เราขอแนะนำให้คุณรวมแพ็กเกจที่สร้างขึ้นไว้ในฟังก์ชัน Composable
ที่กำหนดเอง
รวมแพ็กเกจ UI ในฟังก์ชัน Composable
ของตัวควบคุม
การรวมแพ็กเกจ UI ในฟังก์ชัน Composable
ของตัวควบคุมช่วยให้คุณปรับแต่งงานนำเสนอหรือตรรกะทางธุรกิจ และจัดการสถานะในเครื่องได้หากจำเป็น นักออกแบบยังคงอัปเดตแพ็กเกจ UI เดิมใน Figma ได้ฟรีโดยที่คุณไม่ต้องอัปเดตโค้ด Wrapper
หากต้องการสร้างตัวควบคุมสำหรับตัวติดตามสวิตช์ ให้ทำตามขั้นตอนต่อไปนี้
- ใน Android Studio ให้เปิดไฟล์
java/com/google/relay/example/reflect/ui/components/SwitchControl.kt
- ในฟังก์ชัน
SwitchControl()
Composable
ให้ส่งพารามิเตอร์ต่อไปนี้
trackerData
: ออบเจ็กต์TrackerData
modifier
: วัตถุตกแต่งonLongClick
: การเรียกกลับสำหรับการโต้ตอบเพื่อเปิดใช้การกดติดตามค้างไว้เพื่อแก้ไขและลบ
- แทรกฟังก์ชัน
Switch()
และส่งแป้นกดร่วมcombinedClickable
เพื่อจัดการการคลิกและกดค้าง - ส่งค่าจากออบเจ็กต์
TrackerData
ไปยังฟังก์ชันSwitch()
ซึ่งรวมถึงเมธอดisToggled()
ฟังก์ชัน SwitchControl()
ที่เสร็จสมบูรณ์จะมีลักษณะดังนี้
SwitchControl.kt
package com.google.relay.example.reflect.ui.components
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.google.relay.example.reflect.model.Tracker
import com.google.relay.example.reflect.model.TrackerData
import com.google.relay.example.reflect.model.TrackerType
import com.google.relay.example.reflect.switch.Switch
/*
* A component for controlling switch-type trackers.
*
* SwitchControl is responsible for providing interaction and state management to the stateless
* composable [Switch] generated by Relay. [onLongClick] provides a way for callers to supplement
* the control's intrinsic interactions with, for example, a context menu.
*/
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun SwitchControl(
trackerData: TrackerData,
modifier: Modifier = Modifier,
onLongClick: (() -> Unit)? = null,
) {
Switch(
modifier
.clip(shape = RoundedCornerShape(size = 32.dp))
.combinedClickable(onLongClick = onLongClick) {
trackerData.toggle()
},
emoji = trackerData.tracker.emoji,
title = trackerData.tracker.name,
isChecked = trackerData.isToggled(),
)
}
@Preview
@Composable
fun SwitchControllerPreview() {
val data = TrackerData(
Tracker(
emoji = "🍕",
name = "Ate Pizza",
type = TrackerType.BOOLEAN
)
)
SwitchControl(data)
}
- ในไฟล์
TrackerControl.kt
ให้นำการนำเข้าSwitch
ออก แล้วแทนที่ฟังก์ชันSwitch()
ด้วยการเรียกฟังก์ชันSwitchControl()
- เพิ่มกรณีสำหรับค่าคงที่ตัวแจกแจง
TrackerType.RANGE
และTrackerType.COUNT
บล็อก when
ที่เสร็จสมบูรณ์มีลักษณะคล้ายข้อมูลโค้ดนี้:
TrackerControl.kt
when (trackerData.tracker.type) {
TrackerType.BOOLEAN ->
SwitchControl(
trackerData = trackerData,
onLongClick = { expanded = true },
)
TrackerType.RANGE ->
RangeControl(
trackerData = trackerData,
onLongClick = { expanded = true },
)
TrackerType.COUNT ->
ValueControl(
trackerData = trackerData,
onLongClick = { expanded = true },
)
}
- สร้างโปรเจ็กต์อีกครั้ง ตอนนี้คุณแสดงและโต้ตอบกับอุปกรณ์ติดตามได้แล้ว หน้าจอหลักเสร็จสมบูรณ์แล้ว
7. แมปคอมโพเนนต์ที่มีอยู่
Relay ช่วยให้นักพัฒนาซอฟต์แวร์ปรับแต่งโค้ดที่สร้างขึ้นได้โดยการแทนที่แพ็กเกจ UI ด้วย Composable ที่มีอยู่ วิธีนี้เป็นวิธีที่ยอดเยี่ยมในการแสดงคอมโพเนนต์ที่พร้อมใช้งานทันที หรือแม้กระทั่งระบบการออกแบบที่กำหนดเองลงในโค้ดของคุณ
แมปช่องข้อความ
รูปภาพต่อไปนี้เป็นการออกแบบสำหรับคอมโพเนนต์ Tracker Settings
ในกล่องโต้ตอบเพิ่ม/แก้ไขเครื่องมือติดตาม
นักออกแบบของเราใช้ ReflectTextField
ในการออกแบบ ซึ่งเราก็ได้ติดตั้งใช้งานในโค้ดที่สร้างทับช่องข้อความแบบ Material Design 3 แล้ว Figma ไม่รองรับช่องข้อความโดยค่าเริ่มต้น ดังนั้นโค้ดเริ่มต้นที่ Relay สร้างขึ้นจึงมีลักษณะเพียงแค่การออกแบบเท่านั้น นั่นไม่ใช่การควบคุมการทำงาน
วิธีทดสอบการใช้งานปัจจุบันสำหรับ TrackerSettings
- ใน Android Studio ให้สร้างและเรียกใช้แอปในโปรแกรมจําลอง
- กดค้างที่แถวเครื่องมือติดตาม แล้วเลือกแก้ไข
- แตะช่องข้อความ
Title
และโปรดทราบว่าช่องไม่ตอบสนองต่อการโต้ตอบ
หากต้องการแทนที่การใช้งานจริงสำหรับองค์ประกอบนี้ คุณต้องมี 2 สิ่ง ได้แก่ แพ็กเกจ UI ช่องข้อความและไฟล์การแมป โชคดีที่นักออกแบบของเราได้รวมคอมโพเนนต์ระบบการออกแบบไว้ใน Figma แล้ว และใช้คอมโพเนนต์ช่องข้อความในการออกแบบสำหรับ Tracker Settings
ระบบจะสร้างแพ็กเกจที่ซ้อนกันนี้เป็นทรัพยากร Dependency โดยค่าเริ่มต้น แต่คุณจะใช้การแมปคอมโพเนนต์เพื่อสลับแพ็กเกจ
สร้างไฟล์การแมป
ปลั๊กอิน Relay for Android Studio มีทางลัดสำหรับสร้างไฟล์การแมปคอมโพเนนต์
หากต้องการสร้างไฟล์การแมป ให้ทำตามขั้นตอนต่อไปนี้
- ใน Android Studio ให้คลิกขวาที่แพ็กเกจ UI
text_field
แล้วเลือกสร้างไฟล์การแมป
- กล่องโต้ตอบไฟล์การแมปจะปรากฏขึ้น ป้อนตัวเลือกต่อไปนี้
- ใน Target composable ให้เลือก Use available composable แล้วป้อน
com.google.relay.example.reflect.ui.components.ReflectTextField
- ในไฟล์ที่สร้างขึ้น ให้เลือกสร้างการใช้งาน แล้วยกเลิกการเลือกสร้างตัวอย่างการเขียน
- คลิกสร้างไฟล์การแมป การดำเนินการนี้จะสร้างไฟล์การแมปต่อไปนี้
text_field.json
{
"target": "ReflectTextField",
"package": "com.google.relay.example.reflect.ui.components",
"generateImplementation": true,
"generatePreviews": false,
}
ไฟล์การแมปคอมโพเนนต์จะระบุปลายทางและแพ็กเกจของคลาส Compose และคอลเล็กชันที่ไม่บังคับของออบเจ็กต์ fieldMapping
การแมปฟิลด์เหล่านี้ช่วยให้คุณแปลงพารามิเตอร์แพ็กเกจเป็นพารามิเตอร์ Compose ที่คาดไว้ ในกรณีนี้ API จะเหมือนกัน คุณจึงต้องระบุคลาสเป้าหมายเท่านั้น
- สร้างโปรเจ็กต์อีกครั้ง
- ในไฟล์
trackersettings/
TrackerSettings.kt
ให้ค้นหาฟังก์ชัน ComposableTitleFieldStyleFilledStateEnabledTextConfigurationsInputText()
ที่สร้างขึ้น และสังเกตว่ามีคอมโพเนนต์ReflectTextField
ที่สร้างขึ้น
TrackerSettings.kt (สร้างแล้ว)
@Composable
fun TitleFieldStyleFilledStateEnabledTextConfigurationsInputText(
onTitleChanged: (String) -> Unit,
title: String,
modifier: Modifier = Modifier
) {
ReflectTextField(
onChange = onTitleChanged,
labelText = "Title",
leadingIcon = "search",
trailingIcon = "cancel",
supportingText = "Supporting text",
inputText = title,
state = State.Enabled,
textConfigurations = TextConfigurations.InputText,
modifier = modifier.fillMaxWidth(1.0f).requiredHeight(56.0.dp)
)
}
- สร้างโปรเจ็กต์อีกครั้ง ตอนนี้คุณโต้ตอบกับช่องการตั้งค่าเครื่องมือติดตามได้แล้ว หน้าจอแก้ไขเสร็จสมบูรณ์แล้ว
8. แมปไปยังธีมการเขียน
โดยค่าเริ่มต้น Relay จะสร้างค่าลิเทอรัลสำหรับสีและการพิมพ์ การทำเช่นนี้ช่วยเพิ่มความถูกต้องในการแปล แต่จะป้องกันไม่ให้คอมโพเนนต์ใช้ระบบการกำหนดธีมการเขียน คุณจะมองเห็นได้ชัดเมื่อดูแอปในโหมดมืด
คอมโพเนนต์การนำทางวันแทบจะมองไม่เห็นและสีไม่ถูกต้อง ในการแก้ปัญหานี้ คุณใช้ฟีเจอร์การแมปรูปแบบใน Relay เพื่อลิงก์รูปแบบ Figma กับโทเค็นของธีมในโค้ดที่สร้างขึ้น ซึ่งเป็นการเพิ่มความสอดคล้องกันของภาพระหว่างคอมโพเนนต์ Relay และ Material Design 3 และเปิดใช้การรองรับโหมดมืด
สร้างไฟล์การแมปรูปแบบ
- ใน Android Studio ให้ไปที่ไดเรกทอรี
src/main/ui-package-resources
แล้วสร้างไดเรกทอรีใหม่ชื่อstyle-mappings
ในไดเรกทอรีดังกล่าว ให้สร้างไฟล์figma_styles.json
ที่มีโค้ดต่อไปนี้
figma_styles.json
{
"figma": {
"colors": {
"Reflect Light/background": "md.sys.color.background",
"Reflect Dark/background": "md.sys.color.background",
"Reflect Light/on-background": "md.sys.color.on-background",
"Reflect Dark/on-background": "md.sys.color.on-background",
"Reflect Light/surface": "md.sys.color.surface",
"Reflect Dark/surface": "md.sys.color.surface",
"Reflect Light/on-surface": "md.sys.color.on-surface",
"Reflect Dark/on-surface": "md.sys.color.on-surface",
"Reflect Light/surface-variant": "md.sys.color.surface-variant",
"Reflect Dark/surface-variant": "md.sys.color.surface-variant",
"Reflect Light/on-surface-variant": "md.sys.color.on-surface-variant",
"Reflect Dark/on-surface-variant": "md.sys.color.on-surface-variant",
"Reflect Light/primary": "md.sys.color.primary",
"Reflect Dark/primary": "md.sys.color.primary",
"Reflect Light/on-primary": "md.sys.color.on-primary",
"Reflect Dark/on-primary": "md.sys.color.on-primary",
"Reflect Light/primary-container": "md.sys.color.primary-container",
"Reflect Dark/primary-container": "md.sys.color.primary-container",
"Reflect Light/on-primary-container": "md.sys.color.on-primary-container",
"Reflect Dark/on-primary-container": "md.sys.color.on-primary-container",
"Reflect Light/secondary-container": "md.sys.color.secondary-container",
"Reflect Dark/secondary-container": "md.sys.color.secondary-container",
"Reflect Light/on-secondary-container": "md.sys.color.on-secondary-container",
"Reflect Dark/on-secondary-container": "md.sys.color.on-secondary-container",
"Reflect Light/outline": "md.sys.color.outline",
"Reflect Dark/outline": "md.sys.color.outline",
"Reflect Light/error": "md.sys.color.error",
"Reflect Dark/error": "md.sys.color.error"
},
"typography": {
"symbols": {
"Reflect/headline/large": "md.sys.typescale.headline-large",
"Reflect/headline/medium": "md.sys.typescale.headline-medium",
"Reflect/headline/small": "md.sys.typescale.headline-small",
"Reflect/title/large": "md.sys.typescale.title-large",
"Reflect/title/medium": "md.sys.typescale.title-medium",
"Reflect/title/small": "md.sys.typescale.title-small",
"Reflect/body/large": "md.sys.typescale.body-large",
"Reflect/body/medium": "md.sys.typescale.body-medium",
"Reflect/body/small": "md.sys.typescale.body-small",
"Reflect/label/large": "md.sys.typescale.label-large",
"Reflect/label/medium": "md.sys.typescale.label-medium",
"Reflect/label/small": "md.sys.typescale.label-small"
},
"subproperties": {
"fontFamily": "font",
"fontWeight": "weight",
"fontSize": "size",
"letterSpacing": "tracking",
"lineHeightPx": "line-height"
}
}
},
"compose": {
"colors": {
"md.sys.color.background": "MaterialTheme.colorScheme.background",
"md.sys.color.error": "MaterialTheme.colorScheme.error",
"md.sys.color.error-container": "MaterialTheme.colorScheme.errorContainer",
"md.sys.color.inverse-on-surface": "MaterialTheme.colorScheme.inverseOnSurface",
"md.sys.color.inverse-surface": "MaterialTheme.colorScheme.inverseSurface",
"md.sys.color.on-background": "MaterialTheme.colorScheme.onBackground",
"md.sys.color.on-error": "MaterialTheme.colorScheme.onError",
"md.sys.color.on-error-container": "MaterialTheme.colorScheme.onErrorContainer",
"md.sys.color.on-primary": "MaterialTheme.colorScheme.onPrimary",
"md.sys.color.on-primary-container": "MaterialTheme.colorScheme.onPrimaryContainer",
"md.sys.color.on-secondary": "MaterialTheme.colorScheme.onSecondary",
"md.sys.color.on-secondary-container": "MaterialTheme.colorScheme.onSecondaryContainer",
"md.sys.color.on-surface": "MaterialTheme.colorScheme.onSurface",
"md.sys.color.on-surface-variant": "MaterialTheme.colorScheme.onSurfaceVariant",
"md.sys.color.on-tertiary": "MaterialTheme.colorScheme.onTertiary",
"md.sys.color.on-tertiary-container": "MaterialTheme.colorScheme.onTertiaryContainer",
"md.sys.color.outline": "MaterialTheme.colorScheme.outline",
"md.sys.color.primary": "MaterialTheme.colorScheme.primary",
"md.sys.color.primary-container": "MaterialTheme.colorScheme.primaryContainer",
"md.sys.color.secondary": "MaterialTheme.colorScheme.secondary",
"md.sys.color.secondary-container": "MaterialTheme.colorScheme.secondaryContainer",
"md.sys.color.surface": "MaterialTheme.colorScheme.surface",
"md.sys.color.surface-variant": "MaterialTheme.colorScheme.surfaceVariant",
"md.sys.color.tertiary": "MaterialTheme.colorScheme.tertiary",
"md.sys.color.tertiary-container": "MaterialTheme.colorScheme.tertiaryContainer"
},
"typography": {
"symbols": {
"md.sys.typescale.display-large": "MaterialTheme.typography.displayLarge",
"md.sys.typescale.display-medium": "MaterialTheme.typography.displayMedium",
"md.sys.typescale.display-small": "MaterialTheme.typography.displaySmall",
"md.sys.typescale.headline-large": "MaterialTheme.typography.headlineLarge",
"md.sys.typescale.headline-medium": "MaterialTheme.typography.headlineMedium",
"md.sys.typescale.headline-small": "MaterialTheme.typography.headlineSmall",
"md.sys.typescale.title-large": "MaterialTheme.typography.titleLarge",
"md.sys.typescale.title-medium": "MaterialTheme.typography.titleMedium",
"md.sys.typescale.title-small": "MaterialTheme.typography.titleSmall",
"md.sys.typescale.body-large": "MaterialTheme.typography.bodyLarge",
"md.sys.typescale.body-medium": "MaterialTheme.typography.bodyMedium",
"md.sys.typescale.body-small": "MaterialTheme.typography.bodySmall",
"md.sys.typescale.label-large": "MaterialTheme.typography.labelLarge",
"md.sys.typescale.label-medium": "MaterialTheme.typography.labelMedium",
"md.sys.typescale.label-small": "MaterialTheme.typography.labelSmall"
},
"subproperties": {
"font": "fontFamily",
"weight": "fontWeight",
"size": "fontSize",
"tracking": "letterSpacing",
"line-height": "lineHeight"
}
},
"options": {
"packages": {
"MaterialTheme": "androidx.compose.material3"
}
}
}
}
ไฟล์การแมปธีมมีโครงสร้างที่มีออบเจ็กต์ระดับบนสุด 2 รายการ ได้แก่ figma
และ compose
ภายในออบเจ็กต์เหล่านี้ คำจำกัดความของสีและประเภทจะเชื่อมโยงกันระหว่างสภาพแวดล้อมทั้งสองผ่านโทเค็นระดับกลาง วิธีนี้ช่วยให้สไตล์ Figma หลากหลายแบบแมปกับธีม Compose เพียงรายการเดียวได้ ซึ่งมีประโยชน์เมื่อคุณรองรับธีมสว่างและธีมมืด
- ตรวจสอบไฟล์การแมป โดยเฉพาะอย่างยิ่งวิธีที่ Compose แมปพร็อพเพอร์ตี้การออกแบบตัวอักษรจาก Figma ใหม่ไปยังสิ่งที่ Compose ต้องการ
นำเข้าแพ็กเกจ UI อีกครั้ง
หลังจากสร้างไฟล์การแมปแล้ว คุณต้องนำเข้าแพ็กเกจ UI ทั้งหมดไปยังโปรเจ็กต์อีกครั้ง เนื่องจากระบบจะทิ้งค่าของรูปแบบ Figma ทั้งหมดเมื่อนำเข้าครั้งแรกเนื่องจากไม่มีไฟล์การแมป
หากต้องการนำเข้าแพ็กเกจ UI อีกครั้ง ให้ทำตามขั้นตอนต่อไปนี้
- ใน Android Studio ให้คลิกไฟล์ > ใหม่ > นำเข้าแพ็กเกจ UI กล่องโต้ตอบนำเข้าแพ็กเกจ UI จะปรากฏขึ้น
- ในกล่องข้อความ URL แหล่งที่มาของ Figma ให้ป้อน URL ของไฟล์ต้นฉบับ Figma
- เลือกช่องทำเครื่องหมายแปลรูปแบบ Figma เป็นธีมการเขียน
- เลือกนำเข้าการกำหนดค่าที่กำหนดเอง คลิกไอคอนโฟลเดอร์ แล้วเลือกไฟล์ที่คุณเพิ่งสร้าง:
src/main/ui-package-resources/style-mappings/figma_styles.json
- คลิกถัดไป คุณจะเห็นตัวอย่างแพ็กเกจ UI ของไฟล์
- คลิกสร้าง ระบบจะนำเข้าแพ็กเกจไปยังโปรเจ็กต์
- สร้างโปรเจ็กต์อีกครั้งแล้วเปิดไฟล์
switch/Switch.kt
เพื่อดูโค้ดที่สร้างขึ้น
Switch.kt (สร้างแล้ว)
@Composable
fun ActiveOverlay(
modifier: Modifier = Modifier,
content: @Composable RelayContainerScope.() -> Unit
) {
RelayContainer(
backgroundColor = MaterialTheme.colorScheme.surfaceVariant,
isStructured = false,
radius = 32.0,
content = content,
modifier = modifier.fillMaxWidth(1.0f).fillMaxHeight(1.0f)
)
}
- สังเกตวิธีตั้งค่าพารามิเตอร์
backgroundColor
เป็นช่องMaterialTheme.colorScheme.surfaceVariant
ในออบเจ็กต์ธีม "เขียน" - เรียกใช้โปรเจ็กต์และเปิดโหมดมืดในโปรแกรมจำลอง มีการใช้ธีมอย่างถูกต้องและแก้ไขข้อบกพร่องด้านภาพแล้ว
9. ขอแสดงความยินดี
ยินดีด้วย คุณได้เรียนรู้วิธีผสานรวม Relay เข้ากับแอป Compose แล้ว