นอกจากฟังก์ชันที่ประกอบกันได้ Canvas
แล้ว Compose ยังมีกราฟิกที่มีประโยชน์หลายอย่าง
Modifiers
ซึ่งช่วยในการวาดเนื้อหาที่กำหนดเอง ตัวแก้ไขเหล่านี้มีประโยชน์
เนื่องจากนำไปใช้กับ Composable ใดก็ได้
เครื่องมือแก้ไขการวาด
คำสั่งวาดทั้งหมดจะดำเนินการด้วยตัวแก้ไขการวาดใน Compose ตัวแก้ไขการวาดภาพหลัก 3 รายการใน Compose มีดังนี้
ตัวแก้ไขพื้นฐานสำหรับการวาดคือ drawWithContent
ซึ่งคุณสามารถกำหนด
ลำดับการวาดของ Composable และคำสั่งการวาดที่ออกภายใน
ตัวแก้ไขได้ drawBehind
เป็น Wrapper ที่สะดวกสำหรับ drawWithContent
ซึ่งมี
ลำดับการวาดที่ตั้งค่าเป็นด้านหลังเนื้อหาของ Composable drawWithCache
เรียกใช้ onDrawBehind
หรือ onDrawWithContent
ภายใน - และมี
กลไกสำหรับการแคชออบเจ็กต์ที่สร้างขึ้นในฟังก์ชันเหล่านั้น
Modifier.drawWithContent
: เลือกลำดับการวาด
Modifier.drawWithContent
ช่วยให้คุณ
ดำเนินการ DrawScope
ก่อนหรือหลังเนื้อหาของ
Composable อย่าลืมเรียกใช้ drawContent
เพื่อแสดงเนื้อหาจริงของ
Composable ตัวแก้ไขนี้ช่วยให้คุณกำหนดลำดับการดำเนินการได้ หากต้องการให้ระบบวาดเนื้อหาก่อนหรือหลังการดำเนินการวาดที่กำหนดเอง
ตัวอย่างเช่น หากต้องการแสดงการไล่ระดับสีแบบรัศมีเหนือเนื้อหาเพื่อ สร้างเอฟเฟกต์รูปร่างของไฟฉายบน UI คุณสามารถทำดังนี้
var pointerOffset by remember { mutableStateOf(Offset(0f, 0f)) } Column( modifier = Modifier .fillMaxSize() .pointerInput("dragging") { detectDragGestures { change, dragAmount -> pointerOffset += dragAmount } } .onSizeChanged { pointerOffset = Offset(it.width / 2f, it.height / 2f) } .drawWithContent { drawContent() // draws a fully black area with a small keyhole at pointerOffset that’ll show part of the UI. drawRect( Brush.radialGradient( listOf(Color.Transparent, Color.Black), center = pointerOffset, radius = 100.dp.toPx(), ) ) } ) { // Your composables here }
Modifier.drawBehind
: การวาดด้านหลัง Composable
Modifier.drawBehind
ช่วยให้คุณดำเนินการDrawScope
ที่อยู่เบื้องหลังเนื้อหาที่เขียนได้ซึ่งวาดบนหน้าจอ หากดูการติดตั้งใช้งาน Canvas
คุณอาจสังเกตเห็นว่า Canvas
เป็นเพียง Wrapper ที่สะดวกสำหรับ Modifier.drawBehind
วิธีวาดสี่เหลี่ยมผืนผ้ามุมมนด้านหลัง Text
Text( "Hello Compose!", modifier = Modifier .drawBehind { drawRoundRect( Color(0xFFBBAAEE), cornerRadius = CornerRadius(10.dp.toPx()) ) } .padding(4.dp) )
ซึ่งจะให้ผลลัพธ์ต่อไปนี้

Modifier.drawWithCache
: การวาดและแคชออบเจ็กต์ที่วาด
Modifier.drawWithCache
จะแคชออบเจ็กต์
ที่สร้างไว้ภายใน ระบบจะแคชออบเจ็กต์ตราบใดที่ขนาด
ของพื้นที่วาดภาพยังคงเท่าเดิม หรือออบเจ็กต์สถานะใดๆ ที่อ่านยังไม่
เปลี่ยนแปลง ตัวแก้ไขนี้มีประโยชน์ในการปรับปรุงประสิทธิภาพของการเรียกการวาด เนื่องจากไม่จำเป็นต้องจัดสรรออบเจ็กต์ใหม่ (เช่น Brush, Shader, Path
ฯลฯ)
ที่สร้างขึ้นในการวาด
หรือจะแคชออบเจ็กต์โดยใช้ remember
นอก
ตัวแก้ไขก็ได้ อย่างไรก็ตาม คุณอาจไม่สามารถทำเช่นนี้ได้เสมอไปเนื่องจากคุณอาจไม่มีสิทธิ์เข้าถึง
การเรียบเรียง การใช้ drawWithCache
อาจมีประสิทธิภาพมากกว่าหากใช้
ออบเจ็กต์เพื่อการวาดเท่านั้น
เช่น หากคุณสร้าง Brush
เพื่อวาดการไล่ระดับสีด้านหลัง Text
โดยใช้
drawWithCache
จะแคชออบเจ็กต์ Brush
จนกว่าขนาดของพื้นที่วาดภาพจะเปลี่ยน
แปลง
Text( "Hello Compose!", modifier = Modifier .drawWithCache { val brush = Brush.linearGradient( listOf( Color(0xFF9E82F0), Color(0xFF42A5F5) ) ) onDrawBehind { drawRoundRect( brush, cornerRadius = CornerRadius(10.dp.toPx()) ) } } )

ตัวปรับแต่งกราฟิก
Modifier.graphicsLayer
: ใช้การเปลี่ยนรูปแบบกับ Composable
Modifier.graphicsLayer
เป็นตัวแก้ไขที่ทำให้เนื้อหาของ Composable วาดลงในเลเยอร์การวาด
เลเยอร์มีฟังก์ชันต่างๆ เช่น
- การแยกคำสั่งการวาด (คล้ายกับ
RenderNode
) ไปป์ไลน์การแสดงผลสามารถออกคำสั่งการวาด ที่บันทึกไว้เป็นส่วนหนึ่งของเลเยอร์อีกครั้งได้อย่างมีประสิทธิภาพโดยไม่ต้องเรียกใช้โค้ดแอปพลิเคชันอีกครั้ง - การเปลี่ยนรูปแบบที่มีผลกับคำสั่งการวาดทั้งหมดที่อยู่ในเลเยอร์
- การแปลงเป็นภาพแรสเตอร์เพื่อความสามารถในการคอมโพสิต เมื่อแรสเตอร์เลเยอร์ ระบบจะดำเนินการตาม วิธีการวาดและบันทึกเอาต์พุตลงในบัฟเฟอร์นอกหน้าจอ การคอมโพสิตบัฟเฟอร์ดังกล่าวสำหรับเฟรมถัดไปจะเร็วกว่า การเรียกใช้คำสั่งแต่ละรายการ แต่จะทำงานเป็นบิตแมปเมื่อ ใช้การเปลี่ยนรูปแบบ เช่น การปรับขนาดหรือการหมุน
การแปลงโฉม
Modifier.graphicsLayer
จะแยกคำสั่งวาดภาพของตัวเอง เช่น สามารถใช้การเปลี่ยนรูปแบบต่างๆ ได้โดยใช้ Modifier.graphicsLayer
โดยสามารถเคลื่อนไหวหรือแก้ไขได้โดยไม่ต้องเรียกใช้ Lambda การวาดภาพอีกครั้ง
Modifier.graphicsLayer
ไม่ได้เปลี่ยนขนาดหรือตำแหน่งที่วัดได้ของ
Composable เนื่องจากมีผลเฉพาะในระยะการวาด ซึ่งหมายความว่า Composable อาจซ้อนทับกับ Composable อื่นๆ หากวาดอยู่นอกขอบเขตเลย์เอาต์
คุณใช้ตัวดัดแปลงนี้กับการเปลี่ยนรูปแบบต่อไปนี้ได้
ขยาย - เพิ่มขนาด
scaleX
และ scaleY
จะขยายหรือย่อเนื้อหาในแนวนอนหรือแนวตั้งตามลำดับ
ค่า 1.0f
หมายถึงไม่มีการเปลี่ยนแปลงขนาด ส่วนค่า 0.5f
หมายถึงครึ่งหนึ่งของมิติข้อมูล
Image( painter = painterResource(id = R.drawable.sunset), contentDescription = "Sunset", modifier = Modifier .graphicsLayer { this.scaleX = 1.2f this.scaleY = 0.8f } )
การแปลภาษา
translationX
และ translationY
สามารถเปลี่ยนได้ด้วย graphicsLayer
translationX
จะย้าย Composable ไปทางซ้ายหรือขวา translationY
เลื่อน
Composable ขึ้นหรือลง
Image( painter = painterResource(id = R.drawable.sunset), contentDescription = "Sunset", modifier = Modifier .graphicsLayer { this.translationX = 100.dp.toPx() this.translationY = 10.dp.toPx() } )
การหมุน
ตั้งค่า rotationX
เพื่อหมุนในแนวนอน rotationY
เพื่อหมุนในแนวตั้ง และ
rotationZ
เพื่อหมุนบนแกน Z (การหมุนมาตรฐาน) ค่านี้ระบุเป็นองศา (0-360)
Image( painter = painterResource(id = R.drawable.sunset), contentDescription = "Sunset", modifier = Modifier .graphicsLayer { this.rotationX = 90f this.rotationY = 275f this.rotationZ = 180f } )
Origin
ระบุ transformOrigin
ได้ จากนั้นจะใช้เป็นจุดเริ่มต้น
ในการเปลี่ยนรูปแบบ ตัวอย่างทั้งหมดที่ผ่านมาใช้
TransformOrigin.Center
ซึ่งอยู่ที่ (0.5f, 0.5f)
หากคุณระบุต้นทางที่
(0f, 0f)
การเปลี่ยนรูปแบบจะเริ่มจากมุมซ้ายบนของ
Composable
หากเปลี่ยนต้นทางด้วยrotationZ
การแปลง คุณจะเห็นว่า
รายการหมุนรอบด้านซ้ายบนของ Composable ดังนี้
Image( painter = painterResource(id = R.drawable.sunset), contentDescription = "Sunset", modifier = Modifier .graphicsLayer { this.transformOrigin = TransformOrigin(0f, 0f) this.rotationX = 90f this.rotationY = 275f this.rotationZ = 180f } )
ตัดและปรับรูปร่าง
รูปร่างระบุเส้นขอบที่เนื้อหาจะยึดเมื่อ clip = true
ใน
ตัวอย่างนี้ เราตั้งค่ากล่อง 2 กล่องให้มีคลิปที่แตกต่างกัน 2 คลิป โดยคลิปหนึ่งใช้
graphicsLayer
ตัวแปรคลิป และอีกคลิปหนึ่งใช้ Wrapper ที่สะดวก Modifier.clip
Column(modifier = Modifier.padding(16.dp)) { Box( modifier = Modifier .size(200.dp) .graphicsLayer { clip = true shape = CircleShape } .background(Color(0xFFF06292)) ) { Text( "Hello Compose", style = TextStyle(color = Color.Black, fontSize = 46.sp), modifier = Modifier.align(Alignment.Center) ) } Box( modifier = Modifier .size(200.dp) .clip(CircleShape) .background(Color(0xFF4DB6AC)) ) }
เนื้อหาของกล่องแรก (ข้อความที่ระบุว่า "Hello Compose") จะถูกตัดให้เป็นรูปวงกลม

หากคุณใช้ translationY
กับวงกลมสีชมพูบนสุด คุณจะเห็นว่าขอบเขต
ของ Composable ยังคงเหมือนเดิม แต่วงกลมจะวาดอยู่ใต้วงกลม
ด้านล่าง (และอยู่นอกขอบเขต)

หากต้องการคลิป Composable ไปยังภูมิภาคที่วาด ให้เพิ่ม Modifier.clip(RectangleShape)
อีกรายการที่จุดเริ่มต้นของเชนตัวแก้ไข เนื้อหา
จึงยังคงอยู่ภายในขอบเขตเดิม
Column(modifier = Modifier.padding(16.dp)) { Box( modifier = Modifier .clip(RectangleShape) .size(200.dp) .border(2.dp, Color.Black) .graphicsLayer { clip = true shape = CircleShape translationY = 50.dp.toPx() } .background(Color(0xFFF06292)) ) { Text( "Hello Compose", style = TextStyle(color = Color.Black, fontSize = 46.sp), modifier = Modifier.align(Alignment.Center) ) } Box( modifier = Modifier .size(200.dp) .clip(RoundedCornerShape(500.dp)) .background(Color(0xFF4DB6AC)) ) }

อัลฟ่า
Modifier.graphicsLayer
ใช้เพื่อตั้งค่า alpha
(ความทึบแสง) สำหรับทั้งเลเยอร์ได้ 1.0f
ทึบแสงทั้งหมดและ 0.0f
มองไม่เห็น
Image( painter = painterResource(id = R.drawable.sunset), contentDescription = "clock", modifier = Modifier .graphicsLayer { this.alpha = 0.5f } )

กลยุทธ์การคอมโพสิต
การทำงานกับอัลฟ่าและความโปร่งใสอาจไม่ง่ายเหมือนการเปลี่ยนค่าอัลฟ่าเพียงค่าเดียว
นอกจากการเปลี่ยนอัลฟ่าแล้ว คุณยังมีตัวเลือกในการตั้งค่า
CompositingStrategy
ใน graphicsLayer
ด้วย CompositingStrategy
จะกำหนดวิธีรวมเนื้อหาของ Composable (รวมเข้าด้วยกัน) กับเนื้อหาอื่นๆ ที่วาดบนหน้าจออยู่แล้ว
กลยุทธ์ต่างๆ มีดังนี้
อัตโนมัติ (ค่าเริ่มต้น)
กลยุทธ์การคอมโพสิตจะกำหนดโดยพารามิเตอร์ที่เหลือของ graphicsLayer
โดยจะแสดงเลเยอร์ลงในบัฟเฟอร์นอกหน้าจอหากอัลฟ่าน้อยกว่า
1.0f หรือตั้งค่า RenderEffect
ไว้ เมื่อใดก็ตามที่ค่าอัลฟ่าน้อยกว่า 1f ระบบจะสร้างเลเยอร์การรวมโดยอัตโนมัติเพื่อแสดงเนื้อหา แล้ววาดบัฟเฟอร์นอกหน้าจอนี้ไปยังปลายทางด้วยค่าอัลฟ่าที่สอดคล้องกัน การตั้งค่า
RenderEffect
หรือการเลื่อนเกินจะแสดงเนื้อหาในบัฟเฟอร์นอกหน้าจอเสมอ ไม่ว่าCompositingStrategy
จะตั้งค่าเป็นอะไรก็ตาม
นอกหน้าจอ
เนื้อหาของ Composable จะได้รับการแรสเตอร์เป็นเท็กซ์เจอร์หรือบิตแมปนอกหน้าจอเสมอก่อนที่จะแสดงผลไปยังปลายทาง ซึ่งจะเป็นประโยชน์ในการ
ใช้การดำเนินการ BlendMode
เพื่อมาสก์เนื้อหา และเพื่อประสิทธิภาพเมื่อ
แสดงผลชุดคำสั่งวาดที่ซับซ้อน
ตัวอย่างการใช้ CompositingStrategy.Offscreen
คือการใช้ร่วมกับ BlendModes
ดูตัวอย่างด้านล่าง
สมมติว่าคุณต้องการนำบางส่วนของ Image
ที่ประกอบได้ออกโดยการออกคำสั่งวาดที่
ใช้ BlendMode.Clear
หากคุณไม่ได้ตั้งค่า compositingStrategy
เป็น
CompositingStrategy.Offscreen
BlendMode
จะโต้ตอบกับเนื้อหาทั้งหมด
ด้านล่าง
Image( painter = painterResource(id = R.drawable.dog), contentDescription = "Dog", contentScale = ContentScale.Crop, modifier = Modifier .size(120.dp) .aspectRatio(1f) .background( Brush.linearGradient( listOf( Color(0xFFC5E1A5), Color(0xFF80DEEA) ) ) ) .padding(8.dp) .graphicsLayer { compositingStrategy = CompositingStrategy.Offscreen } .drawWithCache { val path = Path() path.addOval( Rect( topLeft = Offset.Zero, bottomRight = Offset(size.width, size.height) ) ) onDrawWithContent { clipPath(path) { // this draws the actual image - if you don't call drawContent, it wont // render anything this@onDrawWithContent.drawContent() } val dotSize = size.width / 8f // Clip a white border for the content drawCircle( Color.Black, radius = dotSize, center = Offset( x = size.width - dotSize, y = size.height - dotSize ), blendMode = BlendMode.Clear ) // draw the red circle indication drawCircle( Color(0xFFEF5350), radius = dotSize * 0.8f, center = Offset( x = size.width - dotSize, y = size.height - dotSize ) ) } } )
การตั้งค่า CompositingStrategy
เป็น Offscreen
จะสร้างเท็กซ์เจอร์นอกหน้าจอ
เพื่อเรียกใช้คำสั่ง (ใช้ BlendMode
เฉพาะกับ
เนื้อหาของคอมโพสเซเบิลนี้) จากนั้นจะแสดงผลทับสิ่งที่แสดงผลบนหน้าจออยู่แล้ว โดยไม่ส่งผลกระทบต่อเนื้อหาที่วาดไว้แล้ว

หากคุณไม่ได้ใช้ CompositingStrategy.Offscreen
ผลลัพธ์ของการใช้
BlendMode.Clear
จะล้างพิกเซลทั้งหมดในปลายทาง ไม่ว่า
จะมีการตั้งค่าอะไรไว้แล้วก็ตาม ซึ่งจะทำให้บัฟเฟอร์การแสดงผลของหน้าต่าง (สีดำ) ปรากฏ BlendModes
หลายรายการที่เกี่ยวข้องกับอัลฟ่าจะไม่ทำงานตามที่คาดไว้หากไม่มีบัฟเฟอร์นอกหน้าจอ สังเกตวงแหวนสีดำรอบตัวบ่งชี้วงกลมสีแดง

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

โปรดทราบว่าเมื่อใช้ CompositingStrategy.Offscreen
ระบบจะสร้างและแสดงผลเท็กซ์เจอร์นอกหน้าจอ
ที่มีขนาดเท่าพื้นที่วาดภาพกลับมาบนหน้าจอ
คำสั่งวาดภาพใดๆ ที่ทำด้วยกลยุทธ์นี้จะถูก
ตัดไปยังภูมิภาคนี้โดยค่าเริ่มต้น ข้อมูลโค้ดด้านล่างแสดงความแตกต่างเมื่อ
เปลี่ยนไปใช้เท็กซ์เจอร์นอกหน้าจอ
@Composable fun CompositingStrategyExamples() { Column( modifier = Modifier .fillMaxSize() .wrapContentSize(Alignment.Center) ) { // Does not clip content even with a graphics layer usage here. By default, graphicsLayer // does not allocate + rasterize content into a separate layer but instead is used // for isolation. That is draw invalidations made outside of this graphicsLayer will not // re-record the drawing instructions in this composable as they have not changed Canvas( modifier = Modifier .graphicsLayer() .size(100.dp) // Note size of 100 dp here .border(2.dp, color = Color.Blue) ) { // ... and drawing a size of 200 dp here outside the bounds drawRect(color = Color.Magenta, size = Size(200.dp.toPx(), 200.dp.toPx())) } Spacer(modifier = Modifier.size(300.dp)) /* Clips content as alpha usage here creates an offscreen buffer to rasterize content into first then draws to the original destination */ Canvas( modifier = Modifier // force to an offscreen buffer .graphicsLayer(compositingStrategy = CompositingStrategy.Offscreen) .size(100.dp) // Note size of 100 dp here .border(2.dp, color = Color.Blue) ) { /* ... and drawing a size of 200 dp. However, because of the CompositingStrategy.Offscreen usage above, the content gets clipped */ drawRect(color = Color.Red, size = Size(200.dp.toPx(), 200.dp.toPx())) } } }

ModulateAlpha
กลยุทธ์การเรียบเรียงนี้จะปรับค่าอัลฟ่าสำหรับคำสั่งการวาดแต่ละรายการที่บันทึกไว้ใน graphicsLayer
โดยจะไม่สร้างบัฟเฟอร์นอกหน้าจอสำหรับอัลฟ่าที่ต่ำกว่า 1.0f เว้นแต่จะตั้งค่า RenderEffect
จึงทำให้การแสดงผลอัลฟ่ามีประสิทธิภาพมากขึ้น แต่จะแสดงผลลัพธ์ที่แตกต่างกัน
สำหรับเนื้อหาที่ซ้ำซ้อน สำหรับกรณีการใช้งานที่ทราบล่วงหน้าว่าเนื้อหาไม่ทับซ้อนกัน วิธีนี้อาจให้ประสิทธิภาพดีกว่า CompositingStrategy.Auto
ที่มีค่าอัลฟ่าน้อยกว่า 1
อีกตัวอย่างหนึ่งของกลยุทธ์การจัดองค์ประกอบที่แตกต่างกันอยู่ด้านล่าง โดยใช้ค่าอัลฟ่าที่แตกต่างกันกับส่วนต่างๆ ของ Composable และใช้Modulate
กลยุทธ์
@Preview @Composable fun CompositingStrategy_ModulateAlpha() { Column( modifier = Modifier .fillMaxSize() .padding(32.dp) ) { // Base drawing, no alpha applied Canvas( modifier = Modifier.size(200.dp) ) { drawSquares() } Spacer(modifier = Modifier.size(36.dp)) // Alpha 0.5f applied to whole composable Canvas( modifier = Modifier .size(200.dp) .graphicsLayer { alpha = 0.5f } ) { drawSquares() } Spacer(modifier = Modifier.size(36.dp)) // 0.75f alpha applied to each draw call when using ModulateAlpha Canvas( modifier = Modifier .size(200.dp) .graphicsLayer { compositingStrategy = CompositingStrategy.ModulateAlpha alpha = 0.75f } ) { drawSquares() } } } private fun DrawScope.drawSquares() { val size = Size(100.dp.toPx(), 100.dp.toPx()) drawRect(color = Red, size = size) drawRect( color = Purple, size = size, topLeft = Offset(size.width / 4f, size.height / 4f) ) drawRect( color = Yellow, size = size, topLeft = Offset(size.width / 4f * 2f, size.height / 4f * 2f) ) } val Purple = Color(0xFF7E57C2) val Yellow = Color(0xFFFFCA28) val Red = Color(0xFFEF5350)

เขียนเนื้อหาของ Composable ลงในบิตแมป
กรณีการใช้งานทั่วไปคือการสร้าง Bitmap
จาก Composable หากต้องการคัดลอกเนื้อหาของ Composable ไปยัง Bitmap
ให้สร้าง GraphicsLayer
โดยใช้
rememberGraphicsLayer()
เปลี่ยนเส้นทางคำสั่งวาดไปยังเลเยอร์ใหม่โดยใช้ drawWithContent()
และ
graphicsLayer.record{}
จากนั้นวาดเลเยอร์ใน Canvas ที่มองเห็นได้โดยใช้
drawLayer
:
val coroutineScope = rememberCoroutineScope() val graphicsLayer = rememberGraphicsLayer() Box( modifier = Modifier .drawWithContent { // call record to capture the content in the graphics layer graphicsLayer.record { // draw the contents of the composable into the graphics layer this@drawWithContent.drawContent() } // draw the graphics layer on the visible canvas drawLayer(graphicsLayer) } .clickable { coroutineScope.launch { val bitmap = graphicsLayer.toImageBitmap() // do something with the newly acquired bitmap } } .background(Color.White) ) { Text("Hello Android", fontSize = 26.sp) }
คุณสามารถบันทึกบิตแมปไปยังดิสก์และแชร์ได้ ดูรายละเอียดเพิ่มเติมได้ที่ตัวอย่าง โค้ดแบบเต็ม โปรดตรวจสอบสิทธิ์ในอุปกรณ์ก่อนที่จะพยายาม บันทึกลงในดิสก์
ตัวแก้ไขการวาดที่กำหนดเอง
หากต้องการสร้างตัวแก้ไขที่กำหนดเอง ให้ใช้DrawModifier
อินเทอร์เฟซ ซึ่งจะให้สิทธิ์เข้าถึง ContentDrawScope
แก่คุณ ซึ่งเหมือนกับที่แสดงเมื่อใช้ Modifier.drawWithContent()
จากนั้นคุณจะแยกการวาดภาพทั่วไป
ไปยังตัวแก้ไขการวาดภาพที่กำหนดเองเพื่อล้างโค้ดและจัดเตรียม
Wrapper ที่สะดวกได้ เช่น Modifier.background()
เป็น DrawModifier
ที่สะดวก
ตัวอย่างเช่น หากต้องการใช้ Modifier
ที่พลิกเนื้อหาในแนวตั้ง
คุณสามารถสร้างได้ดังนี้
class FlippedModifier : DrawModifier { override fun ContentDrawScope.draw() { scale(1f, -1f) { this@draw.drawContent() } } } fun Modifier.flipped() = this.then(FlippedModifier())
จากนั้นใช้ตัวแก้ไขที่พลิกแล้วนี้กับ Text
Text( "Hello Compose!", modifier = Modifier .flipped() )

แหล่งข้อมูลเพิ่มเติม
ดูตัวอย่างเพิ่มเติมโดยใช้ graphicsLayer
และการวาดที่กำหนดเองได้ในแหล่งข้อมูลต่อไปนี้
แนะนำสำหรับคุณ
- หมายเหตุ: ข้อความลิงก์จะแสดงเมื่อ JavaScript ปิดอยู่
- กราฟิกในฟีเจอร์เขียน
- ปรับแต่งรูปภาพ {:#customize-image}
- Kotlin สำหรับ Jetpack Compose