Jetpack Compose中的Canvas
Posted 川峰
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Jetpack Compose中的Canvas相关的知识,希望对你有一定的参考价值。
Jetpack Compose中的Canvas API 使用起来感觉比传统View中的要简单一些,因为它不需要画笔Paint和画布分开来,大多数直接就是一个函数搞定,当然也有一些限制。
Compose 直接提供了一个叫 Canvas
的 Composable
组件,可以在任何 Composable
组件中直接使用,在 Canvas
的DrawScope
作用域中就可以使用其提供的各种绘制Api进行绘制了。这比传统View要方便的多,传统View中,你只能继承一个View控件,才有机会覆写其onDraw()
方法。
基本图形绘制
常用的API一览表:
API | 描述 |
---|---|
drawLine | 绘制一条线 |
drawRect | 绘制一个矩形 |
drawImage | 绘制一张图片 |
drawRoundRect | 绘制一个圆角矩形 |
drawCircle | 绘制一个圆 |
drawOval | 绘制一个椭圆 |
drawArc | 绘制一条弧线 |
drawPath | 绘制一条路径 |
drawPoints | 绘制一些点 |
这些基本图形的绘制比较简单,基本上尝试一下就知道如何使用了。Compose中的Canvas坐标体系跟传统View一样,也是也左上角为坐标原点的,因此如果是设置偏移量都是针对Canvas左上角而言的。
drawLine
@Composable
fun DrawLineExample()
TutorialText2(text = "strokeWidth")
Canvas(modifier = canvasModifier)
drawLine(
start = Offset(x = 100f, y = 30f),
end = Offset(x = size.width - 100f, y = 30f),
color = Color.Red,
)
drawLine(
start = Offset(x = 100f, y = 70f),
end = Offset(x = size.width - 100f, y = 70f),
color = Color.Red,
strokeWidth = 5f
)
drawLine(
start = Offset(x = 100f, y = 110f),
end = Offset(x = size.width - 100f, y = 110f),
color = Color.Red,
strokeWidth = 10f
)
Spacer(modifier = Modifier.height(10.dp))
TutorialText2(text = "StrokeCap")
Canvas(modifier = canvasModifier)
drawLine(
cap = StrokeCap.Round,
start = Offset(x = 100f, y = 30f),
end = Offset(x = size.width - 100f, y = 30f),
color = Color.Red,
strokeWidth = 20f
)
drawLine(
cap = StrokeCap.Butt,
start = Offset(x = 100f, y = 70f),
end = Offset(x = size.width - 100f, y = 70f),
color = Color.Red,
strokeWidth = 20f
)
drawLine(
cap = StrokeCap.Square,
start = Offset(x = 100f, y = 110f),
end = Offset(x = size.width - 100f, y = 110f),
color = Color.Red,
strokeWidth = 20f
)
Spacer(modifier = Modifier.height(10.dp))
TutorialText2(text = "Brush")
Canvas(modifier = canvasModifier)
drawLine(
brush = Brush.linearGradient(
colors = listOf(Color.Red, Color.Green)
),
start = Offset(x = 100f, y = 30f),
end = Offset(x = size.width - 100f, y = 30f),
strokeWidth = 20f,
)
drawLine(
brush = Brush.radialGradient(
colors = listOf(Color.Red, Color.Green, Color.Blue)
),
start = Offset(x = 100f, y = 70f),
end = Offset(x = size.width - 100f, y = 70f),
strokeWidth = 20f,
)
drawLine(
brush = Brush.sweepGradient(
colors = listOf(Color.Red, Color.Green, Color.Blue)
),
start = Offset(x = 100f, y = 110f),
end = Offset(x = size.width - 100f, y = 110f),
strokeWidth = 20f,
)
Spacer(modifier = Modifier.height(10.dp))
TutorialText2(text = "PathEffect")
Canvas(
modifier = Modifier
.padding(8.dp)
.shadow(1.dp)
.background(Color.White)
.fillMaxWidth()
.height(120.dp)
)
drawLine(
pathEffect = PathEffect.dashPathEffect(floatArrayOf(10f, 10f)),
start = Offset(x = 100f, y = 30f),
end = Offset(x = size.width - 100f, y = 30f),
color = Color.Red,
strokeWidth = 10f
)
drawLine(
pathEffect = PathEffect.dashPathEffect(floatArrayOf(40f, 10f)),
start = Offset(x = 100f, y = 70f),
end = Offset(x = size.width - 100f, y = 70f),
color = Color.Red,
strokeWidth = 10f
)
drawLine(
pathEffect = PathEffect.dashPathEffect(floatArrayOf(70f, 40f)),
start = Offset(x = 100f, y = 110f),
end = Offset(x = size.width - 100f, y = 110f),
cap = StrokeCap.Round,
color = Color.Red,
strokeWidth = 15f
)
val path = Path().apply
moveTo(10f, 0f)
lineTo(20f, 10f)
lineTo(10f, 20f)
lineTo(0f, 10f)
drawLine(
pathEffect = PathEffect.stampedPathEffect(
shape = path,
advance = 30f,
phase = 30f,
style = StampedPathEffectStyle.Rotate
),
start = Offset(x = 100f, y = 150f),
end = Offset(x = size.width - 100f, y = 150f),
color = Color.Green,
strokeWidth = 10f
)
drawLine(
pathEffect = PathEffect.stampedPathEffect(
shape = path,
advance = 30f,
phase = 10f,
style = StampedPathEffectStyle.Morph
),
start = Offset(x = 100f, y = 190f),
end = Offset(x = size.width - 100f, y = 190f),
color = Color.Green,
strokeWidth = 10f
)
drawCircle & drawOval
@Composable
fun DrawCircleExample()
TutorialText2(text = "Oval and Circle")
Canvas(modifier = canvasModifier2)
val canvasWidth = size.width
val canvasHeight = size.height
val radius = canvasHeight / 2
drawOval(
color = Color.Blue,
topLeft = Offset.Zero,
size = Size(1.2f * canvasHeight, canvasHeight)
)
drawOval(
color = Color.Green,
topLeft = Offset(1.5f * canvasHeight, 0f),
size = Size(canvasHeight / 1.5f, canvasHeight)
)
drawCircle(
Color.Red,
center = Offset(canvasWidth - 2 * radius, canvasHeight / 2),
radius = radius * 0.8f,
)
Spacer(modifier = Modifier.height(10.dp))
TutorialText2(text = "DrawStyle")
Canvas(modifier = canvasModifier2)
val canvasWidth = size.width
val canvasHeight = size.height
val radius = canvasHeight / 2
val space = (canvasWidth - 6 * radius) / 4
drawCircle(
color = Color.Red,
radius = radius,
center = Offset(space + radius, canvasHeight / 2),
style = Stroke(width = 5.dp.toPx())
)
drawCircle(
color = Color.Red,
radius = radius,
center = Offset(2 * space + 3 * radius, canvasHeight / 2),
style = Stroke(
width = 5.dp.toPx(),
join = StrokeJoin.Round,
cap = StrokeCap.Round,
pathEffect = PathEffect.dashPathEffect(floatArrayOf(20f, 20f))
)
)
val path = Path().apply
moveTo(10f, 0f)
lineTo(20f, 10f)
lineTo(10f, 20f)
lineTo(0f, 10f)
val pathEffect = PathEffect.stampedPathEffect(
shape = path,
advance = 20f,
phase = 20f,
style = StampedPathEffectStyle.Morph
)
drawCircle(
color = Color.Red,
radius = radius,
center = Offset(canvasWidth - space - radius, canvasHeight / 2),
style = Stroke(
width = 5.dp.toPx(),
join = StrokeJoin.Round,
cap = StrokeCap.Round,
pathEffect = pathEffect
)
)
Spacer(modifier = Modifier.height(10.dp))
TutorialText2(text = "Brush")
Canvas(modifier = canvasModifier2)
val canvasWidth = size.width
val canvasHeight = size.height
val radius = canvasHeight / 2
val space = (canvasWidth - 6 * radius) / 4
drawCircle(
brush = Brush.linearGradient(
colors = listOf(Color.Red, Color.Green),
start = Offset(radius * .3f, radius * .1f),
end = Offset(radius * 2f, radius * 2f)
),
radius = radius,
center = Offset(space + radius, canvasHeight / 2),
)
drawCircle(
brush = Brush.radialGradient(
colors = listOf(Color.Red, Color.Green)
),
radius = radius,
center = Offset(2 * space + 3 * radius, canvasHeight / 2),
)
drawCircle(
brush = Brush.verticalGradient(
colors = listOf(
Color.Red,
Color.Green,
Color.Yellow,
Color.Blue,
Color.Cyan,
Color.Magenta
),
),
radius = radius,
center = Offset(canvasWidth - space - radius, canvasHeight / 2)
)
Spacer(modifier = Modifier.height(10.dp))
Canvas(modifier = canvasModifier2)
val canvasWidth = size.width
val canvasHeight = size.height
val radius = canvasHeight / 2
val space = (canvasWidth - 6 * radius) / 4
drawCircle(
brush = Brush.sweepGradient(
colors = listOf(
Color.Green,
Color.Red,
Color.Blue
),
center = Offset(space + radius, canvasHeight / 2),
),
radius = radius,
center = Offset(space + radius, canvasHeight / 2),
)
drawCircle(
brush = Brush.sweepGradient(
colors = listOf(
Color.Green,
Color.Cyan,
Color.Red,
Color.Blue,
Color.Yellow,
Color.Magenta,
),
// Offset for this gradient is not at center, a little bit left of center
center = Offset(2 * space + 2.7f * radius, canvasHeight / 2),
),
radius = radius,
center = Offset(2 * space + 3 * radius, canvasHeight / 2),
)
drawCircle(
brush = Brush.sweepGradient(
colors = gradientColors,
center = Offset(canvasWidth - space - radius, canvasHeight / 2),
),
radius = radius,
center = Offset(canvasWidth - space - radius, canvasHeight / 2)
)
drawRect
@Composable
private fun DrawRectangleExample()
Spacer(modifier = Modifier.height(10.dp))
TutorialText2(text = "Rectangle")
Canvas(modifier = canvasModifier2)
val canvasWidth = size.width
val canvasHeight = size.height
val space = 60f
val rectHeight = canvasHeight / 2
val rectWidth = (canvasWidth - 4 * space) / 3
drawRect(
color = Color.Blue,
topLeft = Offset(space, rectHeight / 2),
size = Size(rectWidth, rectHeight)
)
drawRect(
color = Color.Green,
topLeft = Offset(2 * space + rectWidth, rectHeight / 2),
size = Size(rectWidth, rectHeight),
sty以上是关于Jetpack Compose中的Canvas的主要内容,如果未能解决你的问题,请参考以下文章