นอกจาก Canvas
Composable แล้ว Compose ยังมีกราฟิกที่มีประโยชน์หลายอย่าง
Modifiers
ซึ่งช่วยในการวาดเนื้อหาที่กำหนดเอง ตัวแก้ไขเหล่านี้มีประโยชน์
เนื่องจากนำไปใช้กับ Composable ใดก็ได้
เครื่องมือแก้ไขการวาด
คำสั่งวาดทั้งหมดจะดำเนินการด้วยตัวแก้ไขการวาดใน Compose ตัวแก้ไขการวาดภาพหลักๆ ใน Compose มี 3 อย่างดังนี้
ตัวแก้ไขพื้นฐานสำหรับการวาดคือ drawWithContent
ซึ่งคุณสามารถกำหนด
ลำดับการวาดของ Composable และคำสั่งการวาดที่ออกภายใน
ตัวแก้ไขได้ drawBehind
เป็น Wrapper ที่สะดวกสำหรับ drawWithContent
ซึ่งมี
ลำดับการวาดที่ตั้งค่าเป็นด้านหลังเนื้อหาของ Composable drawWithCache
เรียกใช้ onDrawBehind
หรือ onDrawWithContent
ภายใน - และมี
กลไกสำหรับการแคชออบเจ็กต์ที่สร้างขึ้นในฟังก์ชันเหล่านั้น
Modifier.drawWithContent
: เลือกลำดับการวาด
Modifier.drawWithContent
ช่วยให้คุณ
ดำเนินการ DrawScope
ก่อนหรือหลังเนื้อหาของ
คอมโพสได้ อย่าลืมเรียกใช้ 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