นอกจากCanvas
คอมโพสิเบิลแล้ว คอมโพซยังมีกราฟิกที่มีประโยชน์หลายรายการ
Modifiers
ซึ่งช่วยในการวาดเนื้อหาที่กำหนดเอง ตัวปรับเปลี่ยนเหล่านี้มีประโยชน์เนื่องจากนำไปใช้กับคอมโพสิเบิลใดก็ได้
ตัวควบคุมการวาด
คำสั่งการวาดทั้งหมดจะดำเนินการด้วยตัวแก้ไขการวาดใน "เขียน" ตัวแก้ไขการวาดหลักๆ ในเครื่องมือเขียนมี 3 รายการดังนี้
ตัวแก้ไขพื้นฐานสำหรับการวาดคือ drawWithContent
ซึ่งคุณจะกำหนดลำดับการวาดของ Composable และคำสั่งการวาดที่ออกภายในตัวแก้ไขได้ drawBehind
เป็น Wrapper ที่สะดวกสำหรับ drawWithContent
ซึ่งตั้งค่าลําดับการวาดไว้ด้านหลังเนื้อหาของคอมโพสิเบิล drawWithCache
เรียกใช้ onDrawBehind
หรือ onDrawWithContent
ภายใน และจัดให้มีกลไกแคชออบเจ็กต์ที่สร้างในนั้น
Modifier.drawWithContent
: เลือกลำดับการวาด
Modifier.drawWithContent
ช่วยให้คุณดำเนินการ DrawScope
ก่อนหรือหลังเนื้อหาของคอมโพสิเบิลได้ อย่าลืมเรียกใช้ drawContent
เพื่อแสดงผลเนื้อหาจริงของคอมโพสิเบิล ตัวแก้ไขนี้ช่วยให้คุณกำหนดลําดับการดําเนินการได้ หากต้องการให้วาดเนื้อหาก่อนหรือหลังการดําเนินการวาดที่กําหนดเอง
ตัวอย่างเช่น หากต้องการแสดงผลไล่ระดับสีแบบรัศมีบนเนื้อหาเพื่อสร้างเอฟเฟกต์รูกุญแจของไฟฉายใน 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
: การวาดด้านหลังคอมโพสิเบิล
Modifier.drawBehind
ช่วยให้คุณดำเนินการDrawScope
ต่างๆ ที่อยู่เบื้องหลังเนื้อหาแบบคอมโพสิเบิลที่วาดบนหน้าจอได้ หากดูการใช้งาน 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
จะแคชออบเจ็กต์ที่สร้างขึ้นภายในไว้ ระบบจะแคชออบเจ็กต์ตราบใดที่ขนาดของพื้นที่วาดภาพเท่าเดิม หรือออบเจ็กต์สถานะที่อ่านไม่เปลี่ยนแปลง ตัวแก้ไขนี้มีประโยชน์ในการปรับปรุงประสิทธิภาพของการเรียกใช้การวาด เนื่องจากช่วยหลีกเลี่ยงความจำเป็นในการ reallocate วัตถุ (เช่น 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
: ใช้การเปลี่ยนรูปแบบกับคอมโพสิเบิล
Modifier.graphicsLayer
คือตัวแก้ไขที่ทำให้เนื้อหาของการวาดแบบคอมโพสิเบิลกลายเป็นเลเยอร์การวาด เลเยอร์มีฟังก์ชันการทำงานหลายอย่าง เช่น
- การแยกคำสั่งวาด (คล้ายกับ
RenderNode
) ไปป์ไลน์การแสดงผลสามารถออกคำสั่งวาดที่บันทึกไว้เป็นส่วนหนึ่งของเลเยอร์อีกครั้งได้อย่างมีประสิทธิภาพโดยไม่ต้องเรียกใช้โค้ดแอปพลิเคชันอีกครั้ง - การเปลี่ยนรูปแบบที่มีผลกับคำสั่งวาดทั้งหมดที่อยู่ในเลเยอร์
- การจัดเรียงพิกเซลเพื่อความสามารถในการจัดองค์ประกอบ เมื่อแรสเตอร์เลเยอร์ ระบบจะดำเนินการตามคำสั่งวาดของเลเยอร์นั้นและจับภาพเอาต์พุตไปยังบัฟเฟอร์นอกหน้าจอ การคอมโพสบัฟเฟอร์ดังกล่าวสําหรับเฟรมต่อๆ ไปจะเร็วกว่าการดําเนินการแต่ละคำสั่ง แต่บัฟเฟอร์จะทํางานแบบบิตแมปเมื่อใช้การเปลี่ยนรูปแบบ เช่น การปรับขนาดหรือการหมุน
การแปลงโฉม
Modifier.graphicsLayer
แยกคำสั่งวาดภาพ เช่น ใช้การเปลี่ยนรูปแบบต่างๆ ได้โดยใช้ Modifier.graphicsLayer
คุณสามารถทำให้ภาพเคลื่อนไหวหรือแก้ไขได้โดยไม่ต้องเรียกใช้ Drawing
lambda อีกครั้ง
Modifier.graphicsLayer
จะไม่เปลี่ยนขนาดหรือตําแหน่งการวัดของคอมโพสิเบิล เนื่องจากจะส่งผลต่อระยะการวาดเท่านั้น ซึ่งหมายความว่าคอมโพสิเบิลของคุณอาจทับซ้อนกับคอมโพสิเบิลอื่นๆ หากวาดนอกขอบเขตเลย์เอาต์
การเปลี่ยนรูปแบบต่อไปนี้ใช้ได้กับตัวแก้ไขนี้
ปรับขนาด - เพิ่มขนาด
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
จะย้ายคอมโพสิเบิลไปทางซ้ายหรือขวา translationY
เลื่อนคอมโพสิเบิลขึ้นหรือลง
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)
การเปลี่ยนรูปแบบจะเริ่มจากมุมซ้ายบนของคอมโพสิเบิล
หากเปลี่ยนจุดเริ่มต้นด้วยการเปลี่ยนรูปแบบ rotationZ
คุณจะเห็นว่ารายการหมุนรอบด้านบนซ้ายของคอมโพสิเบิล
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
และอีกกล่องใช้ตัวห่อที่สะดวก 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 ยังคงเหมือนเดิม แต่วงกลมจะวาดอยู่ใต้วงกลมด้านล่าง (และอยู่นอกขอบเขตของวงกลม)
หากต้องการตัดองค์ประกอบที่คอมโพสิเบิลไปยังภูมิภาคที่วาด ให้เพิ่ม 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
จะกำหนดวิธีคอมโพส (รวม) เนื้อหาของคอมโพสิเบิลเข้ากับเนื้อหาอื่นๆ ที่วาดบนหน้าจอแล้ว
กลยุทธ์ต่างๆ มีดังนี้
อัตโนมัติ (ค่าเริ่มต้น)
กลยุทธ์การคอมโพสจะกำหนดโดยพารามิเตอร์ graphicsLayer
ที่เหลือ โดยจะแสดงผลเลเยอร์เป็นบัฟเฟอร์นอกหน้าจอหากค่าอัลฟาน้อยกว่า 1.0f หรือมีการตั้งค่า RenderEffect
เมื่อใดก็ตามที่แอลฟามีค่าน้อยกว่า 1f ระบบจะสร้างเลเยอร์การคอมโพสโดยอัตโนมัติเพื่อแสดงผลเนื้อหา จากนั้นจะวาดบัฟเฟอร์นอกหน้าจอนี้ไปยังปลายทางด้วยค่าอัลฟาที่เกี่ยวข้อง การตั้งค่า RenderEffect
หรือการเลื่อนผ่านเนื้อหาจะแสดงผลเนื้อหาเป็นบัฟเฟอร์นอกหน้าจอเสมอ ไม่ว่าCompositingStrategy
ที่ตั้งไว้จะเป็นอย่างไรก็ตาม
นอกหน้าจอ
ระบบจะแรสเตอร์เนื้อหาของคอมโพสิเบิลเสมอเป็นพื้นผิวหรือบิตแมปนอกหน้าจอก่อนที่จะแสดงผลไปยังปลายทาง ซึ่งมีประโยชน์สำหรับการใช้การดำเนินการ 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
ตัวอย่างกลยุทธ์การคอมโพสอื่นๆ อีกตัวอย่างหนึ่งมีดังนี้ การใช้อัลฟ่าที่แตกต่างกันกับส่วนต่างๆ ขององค์ประกอบที่คอมโพสได้ และการใช้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)
เขียนเนื้อหาของคอมโพสิเบิลลงในบิตแมป
กรณีการใช้งานทั่วไปคือการสร้าง Bitmap
จากคอมโพสิเบิล หากต้องการคัดลอกเนื้อหาของคอมโพสิเบิลไปยัง Bitmap
ให้สร้าง GraphicsLayer
โดยใช้ rememberGraphicsLayer()
เปลี่ยนเส้นทางคำสั่งวาดไปยังเลเยอร์ใหม่โดยใช้ drawWithContent()
และ
graphicsLayer.record{}
จากนั้นวาดเลเยอร์ในผืนผ้าใบที่มองเห็นได้โดยใช้ 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()
จากนั้นคุณสามารถดึงข้อมูลการดำเนินการวาดทั่วไปไปยังตัวแก้ไขการวาดที่กำหนดเองเพื่อล้างโค้ดและจัดเตรียมตัวห่อที่สะดวก เช่น Modifier.background()
เป็นDrawModifier
ที่สะดวก
ตัวอย่างเช่น หากต้องการใช้ Modifier
ที่พลิกเนื้อหาในแนวตั้ง คุณสามารถสร้าง 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