Graphics và Canvas
Compose cung cấp APIs mạnh mẽ để vẽ custom graphics, từ shapes đơn giản đến drawings phức tạp.
1. Canvas Composable
Phần tiêu đề “1. Canvas Composable”Cơ bản
Phần tiêu đề “Cơ bản”@Composablefun SimpleCanvas() { Canvas(modifier = Modifier.size(200.dp)) { // DrawScope - vẽ ở đây drawRect(color = Color.Blue) }}DrawScope properties
Phần tiêu đề “DrawScope properties”Canvas(modifier = Modifier.size(200.dp)) { val width = size.width // Chiều rộng canvas val height = size.height // Chiều cao canvas val center = this.center // Tâm canvas
// Vẽ tại center drawCircle( color = Color.Red, radius = 50f, center = center )}2. Vẽ Shapes cơ bản
Phần tiêu đề “2. Vẽ Shapes cơ bản”Rectangle
Phần tiêu đề “Rectangle”Canvas(modifier = Modifier.size(200.dp)) { // Filled rectangle drawRect(color = Color.Blue)
// Rectangle với size và offset drawRect( color = Color.Red, topLeft = Offset(20f, 20f), size = Size(100f, 80f) )
// Outlined rectangle drawRect( color = Color.Green, style = Stroke(width = 4f) )}Circle và Oval
Phần tiêu đề “Circle và Oval”Canvas(modifier = Modifier.size(200.dp)) { // Circle drawCircle( color = Color.Blue, radius = 80f, center = center )
// Oval drawOval( color = Color.Red, topLeft = Offset(10f, 50f), size = Size(180f, 100f) )}Canvas(modifier = Modifier.size(200.dp)) { drawLine( color = Color.Blue, start = Offset(0f, 0f), end = Offset(size.width, size.height), strokeWidth = 4f )
// Dashed line drawLine( color = Color.Red, start = Offset(0f, size.height), end = Offset(size.width, 0f), strokeWidth = 4f, pathEffect = PathEffect.dashPathEffect(floatArrayOf(10f, 10f)) )}Canvas(modifier = Modifier.size(200.dp)) { // Arc (partial circle) drawArc( color = Color.Blue, startAngle = 0f, sweepAngle = 270f, // Vẽ 270 độ useCenter = true, // Nối với tâm thành hình quạt topLeft = Offset(20f, 20f), size = Size(160f, 160f) )}3. Path - Vẽ hình dạng tùy ý
Phần tiêu đề “3. Path - Vẽ hình dạng tùy ý”Path cơ bản
Phần tiêu đề “Path cơ bản”Canvas(modifier = Modifier.size(200.dp)) { val path = Path().apply { moveTo(0f, size.height) // Start bottom-left lineTo(size.width / 2, 0f) // Go to top-center lineTo(size.width, size.height) // Go to bottom-right close() // Close path (tam giác) }
drawPath(path, color = Color.Blue)}Bezier curves
Phần tiêu đề “Bezier curves”Canvas(modifier = Modifier.size(200.dp)) { val path = Path().apply { moveTo(0f, size.height / 2)
// Quadratic Bezier (1 control point) quadraticBezierTo( x1 = size.width / 2, y1 = 0f, // Control point x2 = size.width, y2 = size.height / 2 // End point ) }
drawPath( path = path, color = Color.Blue, style = Stroke(width = 4f) )}Cubic Bezier
Phần tiêu đề “Cubic Bezier”Canvas(modifier = Modifier.size(200.dp)) { val path = Path().apply { moveTo(0f, size.height)
// Cubic Bezier (2 control points) cubicTo( x1 = size.width * 0.25f, y1 = 0f, // Control point 1 x2 = size.width * 0.75f, y2 = size.height, // Control point 2 x3 = size.width, y3 = 0f // End point ) }
drawPath( path = path, color = Color.Blue, style = Stroke(width = 4f) )}4. Brush - Gradients và Patterns
Phần tiêu đề “4. Brush - Gradients và Patterns”Linear Gradient
Phần tiêu đề “Linear Gradient”Canvas(modifier = Modifier.size(200.dp)) { drawRect( brush = Brush.linearGradient( colors = listOf(Color.Red, Color.Yellow, Color.Green), start = Offset.Zero, end = Offset(size.width, size.height) ) )}Radial Gradient
Phần tiêu đề “Radial Gradient”Canvas(modifier = Modifier.size(200.dp)) { drawCircle( brush = Brush.radialGradient( colors = listOf(Color.White, Color.Blue), center = center, radius = size.minDimension / 2 ) )}Sweep Gradient
Phần tiêu đề “Sweep Gradient”Canvas(modifier = Modifier.size(200.dp)) { drawCircle( brush = Brush.sweepGradient( colors = listOf(Color.Red, Color.Yellow, Color.Green, Color.Blue, Color.Red), center = center ) )}Gradient với color stops
Phần tiêu đề “Gradient với color stops”Canvas(modifier = Modifier.size(200.dp)) { drawRect( brush = Brush.horizontalGradient( colorStops = arrayOf( 0.0f to Color.Red, 0.3f to Color.Yellow, 1.0f to Color.Green ) ) )}5. Text trên Canvas
Phần tiêu đề “5. Text trên Canvas”Canvas(modifier = Modifier.size(200.dp)) { drawContext.canvas.nativeCanvas.apply { drawText( "Hello Canvas", center.x, center.y, android.graphics.Paint().apply { textSize = 40f color = android.graphics.Color.BLUE textAlign = android.graphics.Paint.Align.CENTER } ) }}Với TextMeasurer (Compose cách)
Phần tiêu đề “Với TextMeasurer (Compose cách)”@Composablefun TextOnCanvas() { val textMeasurer = rememberTextMeasurer()
Canvas(modifier = Modifier.size(200.dp)) { drawText( textMeasurer = textMeasurer, text = "Hello Compose", topLeft = Offset(10f, 10f), style = TextStyle( fontSize = 20.sp, color = Color.Blue ) ) }}6. Transformations
Phần tiêu đề “6. Transformations”Scale, Rotate, Translate
Phần tiêu đề “Scale, Rotate, Translate”Canvas(modifier = Modifier.size(200.dp)) { withTransform({ translate(left = 50f, top = 50f) rotate(degrees = 45f, pivot = Offset(50f, 50f)) scale(scaleX = 1.5f, scaleY = 1.5f, pivot = Offset(50f, 50f)) }) { drawRect( color = Color.Blue, topLeft = Offset.Zero, size = Size(100f, 100f) ) }}inset
Phần tiêu đề “inset”Canvas(modifier = Modifier.size(200.dp)) { // Draw full size drawRect(color = Color.LightGray)
// Draw with inset inset(20f, 20f, 20f, 20f) { drawRect(color = Color.Blue) }}7. Blend Modes
Phần tiêu đề “7. Blend Modes”Canvas(modifier = Modifier.size(200.dp)) { drawCircle( color = Color.Red, radius = 80f, center = Offset(80f, 100f) )
drawCircle( color = Color.Blue, radius = 80f, center = Offset(120f, 100f), blendMode = BlendMode.Multiply // Blend với circle phía dưới )}Các BlendMode phổ biến
Phần tiêu đề “Các BlendMode phổ biến”| Mode | Mô tả |
|---|---|
SrcOver |
Default - vẽ đè lên |
Multiply |
Nhân màu |
Screen |
Sáng hơn |
Overlay |
Kết hợp Multiply và Screen |
Difference |
Hiệu màu |
Clear |
Xóa vùng |
8. drawWithContent và drawBehind
Phần tiêu đề “8. drawWithContent và drawBehind”drawBehind - Vẽ phía sau content
Phần tiêu đề “drawBehind - Vẽ phía sau content”@Composablefun CardWithShadow(content: @Composable () -> Unit) { Box( modifier = Modifier .drawBehind { // Vẽ shadow phía sau drawRoundRect( color = Color.Gray.copy(alpha = 0.3f), topLeft = Offset(4.dp.toPx(), 4.dp.toPx()), cornerRadius = CornerRadius(8.dp.toPx()) ) } .background(Color.White, RoundedCornerShape(8.dp)) ) { content() }}drawWithContent - Vẽ trước hoặc sau content
Phần tiêu đề “drawWithContent - Vẽ trước hoặc sau content”@Composablefun GradientOverlay() { Box( modifier = Modifier .size(200.dp) .drawWithContent { drawContent() // Vẽ content trước
// Vẽ gradient overlay lên trên drawRect( brush = Brush.verticalGradient( colors = listOf(Color.Transparent, Color.Black.copy(alpha = 0.5f)) ) ) } ) { Image( painter = painterResource(R.drawable.image), contentDescription = null ) }}9. Custom Progress Indicator
Phần tiêu đề “9. Custom Progress Indicator”@Composablefun CircularProgress( progress: Float, // 0 to 1 modifier: Modifier = Modifier) { Canvas(modifier = modifier.size(100.dp)) { val strokeWidth = 8.dp.toPx() val diameter = size.minDimension - strokeWidth
// Background circle drawCircle( color = Color.LightGray, radius = diameter / 2, center = center, style = Stroke(width = strokeWidth) )
// Progress arc drawArc( color = Color.Blue, startAngle = -90f, sweepAngle = progress * 360f, useCenter = false, topLeft = Offset(strokeWidth / 2, strokeWidth / 2), size = Size(diameter, diameter), style = Stroke( width = strokeWidth, cap = StrokeCap.Round ) ) }}10. Animated Graphics
Phần tiêu đề “10. Animated Graphics”@Composablefun AnimatedWave() { val infiniteTransition = rememberInfiniteTransition()
val phase by infiniteTransition.animateFloat( initialValue = 0f, targetValue = 2 * Math.PI.toFloat(), animationSpec = infiniteRepeatable( animation = tween(2000, easing = LinearEasing) ) )
Canvas(modifier = Modifier.fillMaxWidth().height(100.dp)) { val path = Path() path.moveTo(0f, size.height / 2)
for (x in 0..size.width.toInt()) { val y = (size.height / 2) + (30 * sin((x * 0.02) + phase)).toFloat() path.lineTo(x.toFloat(), y) }
drawPath( path = path, color = Color.Blue, style = Stroke(width = 4f) ) }}📝 Tóm tắt
Phần tiêu đề “📝 Tóm tắt”| Drawing | Function |
|---|---|
| Rectangle | drawRect() |
| Circle | drawCircle() |
| Oval | drawOval() |
| Line | drawLine() |
| Arc | drawArc() |
| Path | drawPath() |
| Image | drawImage() |
| Text | drawText() |
Modifiers cho drawing
Phần tiêu đề “Modifiers cho drawing”| Modifier | Mục đích |
|---|---|
drawBehind |
Vẽ phía sau content |
drawWithContent |
Vẽ trước/sau content |
drawWithCache |
Cache drawing objects |