绘制线
之前我们学习了Canvas绘制点,我们再看看线怎么画。两点确定一条直线,和之前绘制点一样,绘制线的方法也是在DrawScope中定义,如下所示:
fun drawLine(
color: Color, // 颜色
start: Offset, // 线段开始的坐标点
end: Offset, // 线段结束的坐标点
strokeWidth: Float = Stroke.HairlineWidth, // 线段宽度
cap: StrokeCap = Stroke.DefaultCap, // 处理线段的末端
pathEffect: PathEffect? = null, // 适用于线段的可选效果或图案
/*FloatRange(from = 0.0, to = 1.0)*/
alpha: Float = 1.0f, // 透明度
colorFilter: ColorFilter? = null, // 颜色效果
blendMode: BlendMode = DefaultBlendMode // 混合模式
)
绘制线的方法和绘制点的方法很像,就是多了start和end,二者类型都是Offset,用来确定线段两端的坐标,其他参数和绘制点的没啥区别,我们来看看绘制线段的一个示例:
@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
)
}
}
我们定义了两个点,是线段的起始点,然后定义了一个Canvas可组合项,其中使用DSL的方法绘制线段,将线段颜色定义为红色,线段宽度为30,末端做了圆角处理,效果如下:
还是比较简单的。
绘制矩形
绘制矩形之前来想一个问题,在一张白纸上画一个矩形需要什么条件?需要知道起始点,还需要知道矩形的大小,是的,我们直接看看绘制矩形方法的参数都有哪些:
fun drawRect(
color: Color, // 颜色
topLeft: Offset = Offset.Zero, // 起始点(左上角点的位置)
size: Size = this.size.offsetSize(topLeft), // 大小
/*@FloatRange(from = 0.0, to = 1.0)*/
alpha: Float = 1.0f, // 透明度
style: DrawStyle = Fill, // 样式
colorFilter: ColorFilter? = null, // 颜色效果
blendMode: BlendMode = DefaultBlendMode // 混合模式
)
color是必须填写的,其中还有另外一个绘制方法中,brush替代了这里的color,都和颜色相关,上篇中已经介绍过了,这里就不说了。我们先绘制一个矩形看看:
@Composable
fun DrawRectTest() {
val topLeft = Offset(100f, 100f)
Canvas(modifier = Modifier.size(360.dp)) {
drawRect(
color = Color.Red,
topLeft = topLeft,
size = Size(400f, 600f)
)
}
}
能看到,矩形的左上角点的位置(起点)是(100、100);颜色是红色,大小宽高是400、600;看下效果:
有人会好奇,绘制矩形中有一个参数style之前没遇到过,我们一起看看,它的类型是DrawStyle,就是矩形是否有描边或填充,看看DrawStyle源码:
sealed class DrawStyle
/**
* 绘制时完全用提供的颜色或者图案填充
*/
object Fill : DrawStyle()
class Stroke(
/**
* 画笔的宽度(单位:像素)
*/
val width: Float = 0.0f,
/**
* 画笔斜角值,当连接角度很锐利时,此参数用于控制斜角连接的角度,值必须>=0
*/
val miter: Float = DefaultMiter,
/**
* 线段末端的样式
*/
val cap: StrokeCap = StrokeCap.Butt,
/**
* 设置直线和曲线段在描述路径上连接的处理方式,默认值为StrokeJoin.Miter
*/
val join: StrokeJoin = StrokeJoin.Miter,
/**
* 作用于笔画的效果,null表示要绘制实线
*/
val pathEffect: PathEffect? = null
) : DrawStyle() {
// 省略...
}
DrawStyle是一个密封类,有两个子类Fill和Stoke,前者表示矩形整个被填充,后者表示矩形被描边处理。在Stoke中可以设置一些参数,大部分参数我们都比较熟悉了,需要注意的是,这里的width和前面的一样,默认值也是0.0f,所以必须进行设置,否则就空白无内容。我们一起绘制一个描边空心的矩形:
@Composable
fun DrawRectTest() {
val topLeft = Offset(100f, 100f)
val rectSize = Size(400f, 600f)
Canvas(modifier = Modifier.size(360.dp)) {
drawRect(
color = Color.Red,
topLeft = topLeft,
size = rectSize,
style = Stroke(
width = 30f,
miter = 4f,
cap = StrokeCap.Round
)
)
}
}
style我们设置为Stroke,width为30f,miter为4f,末端圆角处理,效果如下:
Stroke中的参数join之前没有见过,它类型为StrokeJoin,用来设置直线和曲线段在描边路径上连接的处理方式,默认值为StrokeJoin.Miter。先看一些StrokeJoin类:
@Suppress("INLINE_CLASS_DEPRECATED", "EXPERIMENTAL_FEATURE_WARNING")
@Immutable
inline class StrokeJoin internal constructor(@Suppress("unused") private val value: Int) {
companion object {
/**
* 线段之间的连接形成尖角
*/
val Miter = StrokeJoin(0)
/**
* 线段之间的连接是半圆形的
*/
val Round = StrokeJoin(1)
/**
* 将线段对接端的角连接起来,呈现斜角外观
*/
val Bevel = StrokeJoin(2)
}
override fun toString() = when (this) {
Miter -> "Miter"
Round -> "Round"
Bevel -> "Bevel"
else -> "Unknown"
}
}
StrokeJoin类里有一个伴生对象,有三个变量:Miter、Round和Bevel,其默认值为Miter,就是类似于上图所示的尖角,我们修改下上面示例代码中的join:
@Composable
fun DrawRectTest() {
val topLeft = Offset(100f, 100f)
val rectSize = Size(400f, 600f)
Canvas(modifier = Modifier.size(360.dp)) {
drawRect(
color = Color.Red,
topLeft = topLeft,
size = rectSize,
style = Stroke(
width = 30f,
miter = 4f,
// cap = StrokeCap.Round
join = StrokeJoin.Round
)
)
}
}
可以看到,矩形线段连接的地方变得圆滑了。绘制矩形时一定要控制好起始点和矩形的大小,再根据需求选择填充矩形还是进行描边等处理。
绘制圆角矩形
我们再看看圆角矩形怎么绘制,看绘制圆角矩形方法的定义:
fun drawRoundRect(
color: Color,
topLeft: Offset = Offset.Zero,
size: Size = this.size.offsetSize(topLeft),
cornerRadius: CornerRadius = CornerRadius.Zero,
style: DrawStyle = Fill,
/*@FloatRange(from = 0.0, to = 1.0)*/
alpha: Float = 1.0f,
colorFilter: ColorFilter? = null,
blendMode: BlendMode = DefaultBlendMode
)
可以看到,参数和绘制普通矩形基本一样,只是多了一个圆角大小的参数cornerRadius,默认值是CornerRadius,可以通过下面的方法直接进行设置:
@Stable
fun CornerRadius(x: Float, y: Float = x) = CornerRadius(packFloats(x, y))
该方法有两个参数x、y,都是Float类型,分别针对x轴和y轴的半径大小构造一个Radius,需要注意的是x必须设置,y可以不设置,y不设置的话,其默认值为x。那么我们就一起绘制一个圆角矩形吧:
@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(50f), // 圆角半径大小
style = Stroke(
width = 30f,
miter = 4f,
join = StrokeJoin.Round
)
)
}
}
可以看到圆角效果还是非常明显的,大家在使用圆角矩形的时候可以根据实际需求来设置圆角值,其它使用方法和矩形一样。
相关代码已上传到github: github.com/Licarey/com…