/**
* Canvas绘制点
*/
@Composable
fun DrawPointsTest() {
val points = arrayListOf(
Offset(100f, 100f),
Offset(300f, 300f),
Offset(500f, 500f),
Offset(700f, 700f),
Offset(900f, 900f)
)
Canvas(modifier = Modifier.size(360.dp)) {
drawPoints(
points = points,
//类型 PointMode.Points:点 PointMode.Lines:线 PointMode.Polygon:多边形
pointMode = PointMode.Points,
//颜色
color = Color.Blue,
//颜色渐变
// brush = Brush.linearGradient(
// 0.0f to Color.Red,
// 0.5f to Color.Green,
// 1.0f to Color.Blue
// ),
//宽度
strokeWidth = 30f,
//Butt表示线段末端轮廓的起始点和结束点带有平缓的边缘,没有延伸;
//Round表示线段末端以半圆开始和结束的轮廓;
//Square表示线段末端将每个轮廓延伸笔触宽度的一半。
cap = StrokeCap.Round
)
}
}
Canvas组件下用drawPoints绘制点;points属性添加点坐标;pointMode设置类型:PointMode.Points坐标为点。
PointMode.Lines两坐标点形成线段,不够两坐标最后一个坐标点自动省略不显示。
PointMode.Polygon多边形,多坐标点连线,和drawPath绘制路径类似。
color属性设置坐标点的颜色。
brush属性设置坐标点或线的渐变。
strokeWidth属性设置坐标点或线的宽度。
cap设置坐标点或线末端是否为圆角。不设置默认为方形坐标点,设置后为圆形坐标点 。不设置实际是这样的点或线。
/**
* Canvas绘制线
*/
@Composable
fun DrawLineTest() {
val start = Offset(100f, 100f)
val end = Offset(900f, 900f)
Canvas(modifier = Modifier.size(360.dp)) {
drawLine(
//线的颜色
color = Color.Red,
//起始点
start = start,
//末尾点
end = end,
//线宽
strokeWidth = 30f,
//线末端圆角
cap = StrokeCap.Round
)
}
}
绘制线用drawLine,start和end起始点坐标点属性有差别外其他属性和绘制点属性基本一致。
/**
* Canvas绘制矩形(实心)
*/
@Composable
fun DrawRectTest() {
val topLeft = Offset(100f, 100f)
Canvas(modifier = Modifier.size(360.dp)) {
drawRect(
color = Color.Red,
topLeft = topLeft,
size = Size(400f, 600f)
)
}
}
/**
* Canvas绘制矩形(空心)
*/
@Composable
fun DrawRectStrokTest() {
val topLeft = Offset(100f, 100f)
val rectSize = Size(400f, 600f)
Canvas(modifier = Modifier.size(360.dp)) {
drawRect(
color = Color.Red,
topLeft = topLeft,
size = rectSize,
//Stroke设置空心
style = Stroke(
//边框宽度
width = 30f,
//用来设置直线和曲线段在描边路径上连接的处理方式
//StrokeJoin.Miter:尖角 StrokeJoin.Bevel:斜切角 StrokeJoin.Round:圆角
join = StrokeJoin.Round
)
)
}
}
topLeft属性设置居上居左边距,size属性设置矩形大小。
style属性设置矩形样式,Stroke设置为空心矩形,Stroken内width属性设置矩形线的宽度,join属性设置边框角的形状。
join设置为StrokeJoin.Bevel时矩形边框是这样的斜切角:
不设置或设置为StrokeJoin.Miter为直角。
/**
* Canvas绘制圆角矩形
*/
@Composable
fun DrawRoundRectTest() {
val topLeft = Offset(100f, 100f)
val rectSize = Size(400f, 600f)
Canvas(modifier = Modifier.size(360.dp)) {
drawRoundRect(
color = Color.Red,
topLeft = topLeft,
size = rectSize,
//圆角设置
cornerRadius = CornerRadius(100f),
//Stroke设置空心
style = Stroke(
//边框宽度
width = 30f,
//用来设置直线和曲线段在描边路径上连接的处理方式
//StrokeJoin.Miter:尖角 StrokeJoin.Bevel:斜切角 StrokeJoin.Round:圆角
join = StrokeJoin.Round
)
)
}
}
绘制圆角矩形用drawRoundRect,当矩形宽高一样时,并且圆角角度设置足够大时,矩形就会变成圆形,设置圆角用cornerRadius属性。实心不设置style属性就行。
/**
* Canvas绘制圆
*/
@Composable
fun DrawCircleTest() {
Canvas(modifier = Modifier.size(360.dp)) {
drawCircle(
color = Color.Blue,
//居中
center = center,
//圆的半径
radius = 300f,
//空心设置
style = Stroke(
width = 30f
)
)
}
}
drawRoundRect虽然可以绘制圆,但是需要设置矩形宽高一致时并且圆角足够大时才变成圆形。直接用drawCircle可以直接设置圆,只需要通过radius属性设置圆的半径就行了。
/**
* Canvas绘制椭圆
*/
@Composable
fun DrawOvalTest() {
val topLeft = Offset(100f, 100f)
val ovalSize = Size(600f, 800f)
Canvas(modifier = Modifier.size(360.dp)) {
drawOval(
color = Color.Blue,
//起始位置
topLeft = topLeft,
//大小设置
size = ovalSize,
//空心设置
style = Stroke(
width = 30f
)
)
}
}
绘制椭圆用drawOval,当椭圆宽高相同时椭圆也会变成圆。
所以Canvas下的drawOval、drawCircle、drawRoundRect都可以设置圆。
/**
* Canvas绘制圆弧
*/
@Composable
fun DrawAcrTest() {
val ovalSize = Size(600f, 600f)
Canvas(modifier = Modifier.size(360.dp)) {
drawArc(
color = Color.Blue,
size = ovalSize,
//起始角度(3点钟方向开始)
startAngle = 0f,
//扫描角度
sweepAngle = 100f,
//中心对齐
useCenter = true,
//空心设置
style = Stroke(
width = 20f
)
)
}
}
设置圆弧用drawArc,只需要设置下startAngle和sweepAngle起始角度就可以画出一个扇形或者弧形。
当useCenter属性设置为false时画出就是弧形。
/**
* Canvas绘制图片
*/
@Composable
fun DrawImageTest() {
val context = LocalContext.current
val bitmap = BitmapFactory.decodeResource(context.resources, R.drawable.img)
val image = bitmap.asImageBitmap()
Canvas(modifier = Modifier.size(360.dp)) {
//image -要绘制的源图像
//srcOffset -可选偏移量,表示要绘制的源图像的左上角偏移量,默认为图像的原点
//srcSize -相对于srcOffset绘制的源图像的可选尺寸,默认为图像的宽度和高度
//dstOffset -可选偏移量,表示绘制给定图像的目的地的左上角偏移量,默认为当前平移的原点,开始于绘制图像的目的地的左上角偏移量
//dstSize -绘制目标的可选尺寸,默认为srcSize
//alpha -应用于图像的不透明度从0.0f到1.0f,分别表示完全透明到完全不透明
//样式-指定图像是填充还是矩形描边绘制
//colorFilter -当绘制到目的地时,将colorFilter应用于图像
//blendMode -应用于目标的混合算法
//filterQuality -当图像被缩放并绘制到目的地时,应用于图像的采样算法。默认为FilterQuality。使用双线性采样算法进行缩放
drawImage(
image = image,
srcOffset = IntOffset(0, 0),
srcSize = IntSize(400, 400),
dstOffset = IntOffset(100, 100),
dstSize = IntSize(800, 800)
)
}
}
Canvas下绘制图片用drawImage。
/**
* Canvas绘制路径
*/
@Composable
fun DrawPathTest() {
val path = Path()
path.moveTo(100f, 100f)
path.lineTo(100f, 300f)
path.lineTo(400f, 600f)
path.lineTo(700f, 300f)
path.lineTo(700f, 100f)
path.lineTo(650f, 50f)
path.lineTo(600f, 50f)
path.lineTo(400f, 200f)
path.lineTo(200f, 50f)
path.lineTo(150f, 50f)
// path.quadraticBezierTo(800f, 700f, 600f, 100f) // 二阶贝塞尔曲线
// path.cubicTo(700f, 200f, 800f, 400f, 100f, 100f) // 三阶贝塞尔曲线
path.close()
Canvas(modifier = Modifier.size(360.dp)) {
drawPath(
//路径设置
path = path,
//颜色设置
color = Color.Red,
//空心设置
style = Stroke(
width = 10f
)
)
}
}
Canvas下使用drawPath绘制路径,drawPath下path属性路径坐标,路径可用quadraticBezierTo属性添加二阶贝塞尔曲线,cubicTo属性添加三阶贝塞尔曲线。
/**
* 使用混合模式
*/
@Composable
fun DrawBlendModeTest() {
Canvas(modifier = Modifier.fillMaxSize()) {
//左胳膊
drawRoundRect(
color = Color(0xFFA5CA39),
topLeft = Offset(100f, 400f),
size = Size(120f, 400f),
//圆角设置
cornerRadius = CornerRadius(100f)
)
//右胳膊
drawRoundRect(
color = Color(0xFFA5CA39),
topLeft = Offset(780f, 400f),
size = Size(120f, 400f),
//圆角设置
cornerRadius = CornerRadius(100f)
)
//左触角
drawLine(
//线的颜色
color = Color(0xFFA5CA39),
//起始点
start = Offset(350f, 100f),
//末尾点
end = Offset(400f, 200f),
//线宽
strokeWidth = 20f,
//线末端圆角
cap = StrokeCap.Round
)
//右触角
drawLine(
//线的颜色
color = Color(0xFFA5CA39),
//起始点
start = Offset(650f, 100f),
//末尾点
end = Offset(600f, 200f),
//线宽
strokeWidth = 20f,
//线末端圆角
cap = StrokeCap.Round
)
//头
drawArc(
color = Color(0xFFA5CA39),
size = Size(500f, 500f),
topLeft = Offset(250f, 150f),
//起始角度
startAngle = 180f,
//扫描角度
sweepAngle = 180f,
//中心对齐
useCenter = true
)
//左眼
drawPoints(
points = arrayListOf(
Offset(380f, 280f)
),
pointMode = PointMode.Points,
color = Color(0xFFFFFFFF),
strokeWidth = 50f,
cap = StrokeCap.Round
)
//右眼
drawPoints(
points = arrayListOf(
Offset(620f, 280f)
),
pointMode = PointMode.Points,
color = Color(0xFFFFFFFF),
strokeWidth = 50f,
cap = StrokeCap.Round
)
//身体
drawPath(
path = Path().apply {
addRoundRect(
RoundRect(
rect = Rect(
offset = Offset(250f, 420f),
size = Size(500f, 480f),
),
bottomLeft = CornerRadius(100f, 100f),
bottomRight = CornerRadius(100f, 100f),
)
)
},
color = Color(0xFFA5CA39)
)
//左腿
drawPath(
path = Path().apply {
addRoundRect(
RoundRect(
rect = Rect(
offset = Offset(350f, 880f),
size = Size(120f, 240f),
),
bottomLeft = CornerRadius(100f, 100f),
bottomRight = CornerRadius(100f, 100f),
)
)
},
color = Color(0xFFA5CA39)
)
//右腿
drawPath(
path = Path().apply {
addRoundRect(
RoundRect(
rect = Rect(
offset = Offset(550f, 880f),
size = Size(120f, 240f),
),
bottomLeft = CornerRadius(100f, 100f),
bottomRight = CornerRadius(100f, 100f),
)
)
},
color = Color(0xFFA5CA39)
)
}
}
我这里使用的是drawRoundRect绘制圆角矩形的方式绘制的胳膊,使用drawLine绘制线的方式绘制的触角,使用drawArc绘制圆弧的方式绘制的头,使用drawPoints绘制点的方式绘制的眼睛,使用drawPath绘制路径的方式绘制的身体和腿。
当然绘制各种形状方法不是唯一性的,欢迎探讨更多更简单实用的Compose绘制方法。