ใน Glimmer ของ Jetpack Compose คอมโพเนนต์ surface เป็นองค์ประกอบที่ใช้สร้างสรรค์พื้นฐานที่แสดงพื้นที่ภาพที่แตกต่างกันหรือขอบเขตทางกายภาพสำหรับคอมโพเนนต์ต่างๆ เช่น ปุ่มและการ์ด
แพลตฟอร์มมีหน้าที่รับผิดชอบต่อคุณสมบัติทางภาพและทางกายภาพต่อไปนี้
- Clipping: ครอบตัดองค์ประกอบย่อยให้เป็นรูปร่างที่ระบุ
- เส้นขอบ: วาดเส้นขอบด้านในเพื่อเน้นขอบเขตของคอมโพเนนต์ เมื่อ โฟกัสอยู่ จะวาดเส้นขอบที่กว้างขึ้นพร้อมไฮไลต์ที่โฟกัส
- พื้นหลัง: ใช้สีพื้นหลังกับพื้นที่ผิว
- เอฟเฟกต์ความลึก: แสดงผล
DepthEffectเงาตามสถานะของคอมโพเนนต์ (เช่น ค่าเริ่มต้นเทียบกับโฟกัส) - สีเนื้อหา: ระบุสีสำหรับข้อความและไอคอนภายในพื้นผิว ซึ่งคำนวณจากสีพื้นหลังโดยค่าเริ่มต้น
- สถานะการโต้ตอบ: วาดภาพซ้อนทับที่กดเมื่อกดพื้นผิว และเส้นขอบที่กว้างขึ้นพร้อมไฮไลต์เมื่อโฟกัส
ตัวอย่าง: สร้างพื้นผิว
โค้ดต่อไปนี้สร้างพื้นผิวที่มีการตัดขอบ พื้นหลัง และเส้นขอบเริ่มต้น
@Composable fun SurfaceSample() { Box(Modifier.surface().padding(horizontal = 24.dp, vertical = 20.dp)) { Text("This is a surface") } }
Interaction and Focus
Surfaces aren't focusable by default, so users can't interact with them. In most
cases, surfaces should be interactive to let users consistently move focus and
navigate between components. You can use the Compose focusable modifer
for surfaces that are only intended to be focusable, or the Compose
clickable modifer and other modifiers for surfaces that require actions.
You can create a focusable surface by combining a surface modifier with the
focusable modifier:
@Composable fun FocusableSurfaceSample() { val interactionSource = remember { MutableInteractionSource() } Box( Modifier.surface( // Provide the same interaction source here and to focusable to make sure that // surface appears focused when interacted with. interactionSource = interactionSource ) .focusable(interactionSource = interactionSource) .padding(horizontal = 24.dp, vertical = 20.dp) ) { Text("This is a focusable surface") } }
Key points about the code
- Shared interaction source: Both .
surface()and .focusable()must share the sameinteractionSource. This lets the surface react to focus changes.
Similarly, you can create a clickable surface:
@Composable fun ClickableSurfaceSample() { val interactionSource = remember { MutableInteractionSource() } Box( Modifier.surface( // Provide the same interaction source here and to clickable to make sure that // surface appears focused and pressed when interacted with interactionSource = interactionSource ) .clickable(interactionSource = interactionSource, onClick = {}) .padding(horizontal = 24.dp, vertical = 20.dp) ) { Text("This is a clickable surface") } }
ประเด็นสำคัญเกี่ยวกับโค้ด
แหล่งที่มาของการโต้ตอบที่แชร์: ทั้ง 2 รายการ
surface()และclickable()ต้อง ใช้interactionSourceเดียวกัน ซึ่งจะช่วยให้มั่นใจได้ว่าสถานะภาพ (เช่น กดหรือโฟกัส) จะซิงค์กัน ทำให้พื้นผิวตอบสนองต่ออินพุตของผู้ใช้ในลักษณะที่มองเห็นได้การจัดลำดับตัวแก้ไข: ลำดับของตัวแก้ไขมีความสำคัญ เนื่องจาก
surface()ตัดเลย์เอาต์โดยวางไว้ก่อนclickable()ช่วยให้มั่นใจว่าเป้าหมายการสัมผัสจะจำกัดอยู่แค่รูปร่างของพื้นผิว หากclickable()มาก่อน พื้นที่การโต้ตอบอาจขยายออกไปนอกขอบเขตที่มองเห็นได้และถูกตัด ของคอมโพเนนต์
SurfaceDepthEffect
คลาส SurfaceDepthEffect จะจัดการการเปลี่ยนเงาระหว่างสถานะการโต้ตอบ ดังนี้
depthEffect: เอฟเฟกต์เงาที่ใช้เมื่อพื้นผิวอยู่ในสถานะเริ่มต้นfocusedDepthEffect: เอฟเฟกต์เงาที่ใช้เมื่อโฟกัสพื้นผิว