我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Jetpack Compose Canvas绘制超详细介绍

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Jetpack Compose Canvas绘制超详细介绍

1. Canvas

@Composable
fun Canvas(
	modifier: Modifier,
	onDraw: DrawScope.() -> Unit
) = Spacer(modifier.drawBehind(onDraw))
  • modifier:这里主要作用是指定画布的大小。
  • onDraw就是执行具体的绘制。可以看到它提供了一个绘图环境的作用域 DrawScope,这里提供有我们经常使用的绘图api和属性,比如drawLinesize等。

先来一个简单的例子看看如何使用:

Canvas(modifier = Modifier.fillMaxSize()) {
    val canvasWidth = size.width
    val canvasHeight = size.height
    drawLine(
        start = Offset(x = canvasWidth, y = 0f),
        end = Offset(x = 0f, y = canvasHeight),
        color = Color.Blue
    )
}

画一条线,开始和结束位置分别是画布的右上角和左下角。效果如下:

2. 绘制方法

1. drawLine

drawLine在上面的例子中简单说明了,当然它不止这些功能。

	fun drawLine(
        color: Color, //或 brush: Brush,
        start: Offset,
        end: Offset,
        strokeWidth: Float = Stroke.HairlineWidth,
        cap: StrokeCap = Stroke.DefaultCap,
        pathEffect: PathEffect? = null,
        
        alpha: Float = 1.0f,
        colorFilter: ColorFilter? = null,
        blendMode: BlendMode = DefaultBlendMode
    )
  • 指定线的颜色用color
  • 渐变色可以使用brush,本系列第三篇有说明。
  • strokeWidth 是线的宽度,默认是1px。
  • cap是线头的形状,默认是StrokeCap.Butt平头。还有StrokeCap.Round圆头,StrokeCap.Square方头。这部分和Android中的Paint是一样的。平头和方头的不同在于是否延伸出来的部分。

pathEffect是线段的效果,比如虚线这种就是使用PathEffect.dashPathEffect(intervals: FloatArray, phase: Float = 0f) ,举一个例子:

PathEffect.dashPathEffect(floatArrayOf(20f, 10f), 10f)

intervals中的20f表示虚线的宽度,10f是间隔宽度。phase的10f表示初始的偏移距离。所以一开始偏移10f,就会导致第一段的线段被"裁剪"10f,具体效果如下图:

  • alpha 是线段的透明度。
  • colorFilter是颜色过滤器,本系列第四篇有说明,这里就不重复介绍了。
  • blendMode:混合模式。这个不在本篇的范围内,后面有机会我会详细说一下。有兴趣可以先看看文末的参考文章。

2. drawRect

绘制矩形方法,属性与drawLine大同小异,下面说一些不同点。

	fun drawRect(
        color: Color,
        topLeft: Offset = Offset.Zero,
        size: Size = this.size.offsetSize(topLeft),
        
        alpha: Float = 1.0f,
        style: DrawStyle = Fill,
        colorFilter: ColorFilter? = null,
        blendMode: BlendMode = DefaultBlendMode
    )
  • topLeft是用来指定左上角的偏移量,如果没有指定那么默认从当前画布左上角开始。
  • size用来指定矩形大小,如果没有指定那么默认就是当前画布的大小。
  • style是指实心还是空心。默认Fill实心,Stroke空心。

3. drawRoundRect

绘制圆角矩形基本与矩形一致,只是多了一个设置圆角大小的参数drawRoundRect,这里就不多说明了。

4. drawImage

绘制图片方法

	fun drawImage(
        image: ImageBitmap,
        class="lazy" data-srcOffset: IntOffset = IntOffset.Zero,
        class="lazy" data-srcSize: IntSize = IntSize(image.width, image.height),
        dstOffset: IntOffset = IntOffset.Zero,
        dstSize: IntSize = class="lazy" data-srcSize,
        
        alpha: Float = 1.0f,
        style: DrawStyle = Fill,
        colorFilter: ColorFilter? = null,
        blendMode: BlendMode = DefaultBlendMode
    )
  • image:需要绘制的图片,具体可以使用ImageBitmap.imageResource(id = R.drawable.xxx)方法获取。
  • class="lazy" data-srcOffset:需要绘制图片的左上角偏移量,默认为图像的原点。
  • class="lazy" data-srcSize: 图片相对于class="lazy" data-srcOffset的尺寸,默认为图像的宽高。
  • dstOffset: 绘制图片的相对左上角的偏移量,这默认为图像的原点。
  • dstSize:绘制图片的大小,默认为class="lazy" data-srcSize

下面的代码是绘制一张图片的右下角区域,相对画布偏移50 * 50,绘制的大小是200 * 200。

 	val imageBitmap = ImageBitmap.imageResource(id = R.mipmap.ic_launcher)
    Canvas(modifier = Modifier.fillMaxSize()) {
        drawImage(
            image = imageBitmap,
            class="lazy" data-srcOffset = IntOffset(imageBitmap.width / 2,imageBitmap.height / 2),
            class="lazy" data-srcSize = IntSize(imageBitmap.width, imageBitmap.height),
            dstOffset = IntOffset(50,50),
            dstSize = IntSize(200,200)
        )
    }

效果如下:

5. drawCircle

绘制圆形方法

	fun drawCircle(
        color: Color,
        radius: Float = size.minDimension / 2.0f,
        center: Offset = this.center,
        
        alpha: Float = 1.0f,
        style: DrawStyle = Fill,
        colorFilter: ColorFilter? = null,
        blendMode: BlendMode = DefaultBlendMode
    )
  • radius:圆的半径大小。
  • center:圆心位置。

6. drawArc

drawArc可以用来绘制弧形或是扇形

	fun drawArc(
        color: Color,
        startAngle: Float,
        sweepAngle: Float,
        useCenter: Boolean,
        topLeft: Offset = Offset.Zero,
        size: Size = this.size.offsetSize(topLeft),
        
        alpha: Float = 1.0f,
        style: DrawStyle = Fill,
        colorFilter: ColorFilter? = null,
        blendMode: BlendMode = DefaultBlendMode
    )
  • startAngle: 开始角度
  • sweepAngle: 弧线扫过的角度
  • useCenter: 弧线是否过圆心

这里就不举例说明了,可以用styleuseCenter属性自行组合尝试。

7. drawPath

绘制路径方法

	fun drawPath(
        path: Path,
        color: Color,
        
        alpha: Float = 1.0f,
        style: DrawStyle = Fill,
        colorFilter: ColorFilter? = null,
        blendMode: BlendMode = DefaultBlendMode
    )

其实和Android中的path使用一样,围绕着moveTo、lineTo、close这些方法,也就不详细说明了。

8. drawPoints

绘制点的方法

	fun drawPoints(
        points: List<Offset>,
        pointMode: PointMode,
        color: Color,
        strokeWidth: Float = Stroke.HairlineWidth,
        cap: StrokeCap = StrokeCap.Butt,
        pathEffect: PathEffect? = null,
        
        alpha: Float = 1.0f,
        colorFilter: ColorFilter? = null,
        blendMode: BlendMode = DefaultBlendMode
    )
  • points:点的偏移位置
  • pointMode:点的绘制模式,PointMode.Points分别画出每个点。PointMode.Lines 每两个点画成一条线段。 如果点数是奇数,则忽略最后一个点。PointMode.Polygon 连接所有的点。

最后还有一个绘制椭圆方法drawOval,用法大同小异,就不说明了。

3. DrawScope拓展方法

1. inset

同时从左到上转换DrawScope坐标空间,并修改当前绘制区域的尺寸。

inline fun DrawScope.inset(
    left: Float,
    top: Float,
    right: Float,
    bottom: Float,
    block: DrawScope.() -> Unit
) {...}

inset有点像是在原有的画布上,嵌入了一个"新"的画布,设置的left,top就是相应的padding。

	Canvas(modifier = Modifier.fillMaxSize()){
        drawRect(
            color = Color.Blue,
        )
        inset(100f, 100f, 100f, 100f) {
            drawRect(
                color = Color.Red,
            )
        }
    }

2. translate

平移绘制区域

inline fun DrawScope.translate(
    left: Float = 0.0f,
    top: Float = 0.0f,
    block: DrawScope.() -> Unit
) {...}

只需要设置left、top方向移动的距离即可。

3. rotate与rotateRad

旋转绘制区域

inline fun DrawScope.rotate(
    degrees: Float,
    pivot: Offset = center,
    block: DrawScope.() -> Unit
) {...}

inline fun DrawScope.rotateRad(
    radians: Float,
    pivot: Offset = center,
    block: DrawScope.() -> Unit
) {...}
  • degrees是旋转了多少角度。
  • radians是旋转了多少弧度。
  • pivot 是旋转的中心点,默认是中心。

4. scale

缩放绘制区域。

inline fun DrawScope.scale(
    scaleX: Float,
    scaleY: Float,
    pivot: Offset = center,
    block: DrawScope.() -> Unit
) {...}

指定x、y方向上的缩放倍数即可。

5. clipRect

裁剪给定的矩形区域

inline fun DrawScope.clipRect(
    left: Float = 0.0f,
    top: Float = 0.0f,
    right: Float = size.width,
    bottom: Float = size.height,
    clipOp: ClipOp = ClipOp.Intersect,
    block: DrawScope.() -> Unit
) {...}
  • clipOpClipOp.Intersect是裁剪矩形的里面,ClipOp.Difference是裁剪矩形的外面。

看个简单的例子,便于你的理解:

	Canvas(modifier = Modifier.fillMaxSize()){
        drawRect(
            color = Color.Blue,
        )
        clipRect(200f, 200f, clipOp = ClipOp.Intersect) {
            drawRect(
                color = Color.Yellow,
            )
        }
    }

左边是ClipOp.Intersect,右边是ClipOp.Difference

clipPath同理。

6. drawIntoCanvas

可以直接调用底层Canvas绘制的方法。我们用它实现一开始的drawLine例子,画一条对角线:

	Canvas(modifier = Modifier.fillMaxSize()) {
        val canvasWidth = size.width
        val canvasHeight = size.height
        drawIntoCanvas {
            val paint = Paint()
            paint.color = Color.Blue
            paint.strokeWidth = 1f
            it.drawLine(
                p1 = Offset(canvasWidth,0f),
                p2 = Offset(0f,canvasHeight),
                paint = paint
            )
        }
    }

其中drawLine方法,并不是一开始DrawScope中的drawLine:

actual typealias NativeCanvas = android.graphics.Canvas
private val EmptyCanvas = android.graphics.Canvas()
@PublishedApi internal class AndroidCanvas() : Canvas {
    @PublishedApi internal var internalCanvas: NativeCanvas = EmptyCanvas
	override fun drawLine(p1: Offset, p2: Offset, paint: Paint) {
        internalCanvas.drawLine(
            p1.x,
            p1.y,
            p2.x,
            p2.y,
            paint.asFrameworkPaint()
        )
    }
}

可以看到最终调用了Android的Canvas api。

7. withTransform

执行1个或多个转换。也就是上面平移旋转这些可以一块执行。

inline fun DrawScope.withTransform(
    transformBlock: DrawTransform.() -> Unit,
    drawBlock: DrawScope.() -> Unit
) {...}

4.参考

Compose 中的图形

Jetpack Compose 绘制 Canvas

到此这篇关于Jetpack Compose Canvas绘制超详细介绍的文章就介绍到这了,更多相关Jetpack Compose Canvas内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Jetpack Compose Canvas绘制超详细介绍

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Jetpack Compose Canvas绘制超详细介绍

Canvas 是允许您在屏幕上指定区域并在此区域上执行绘制的组件。您必须使用修饰符指定尺寸,无论是通过Modifier.size修饰符指定确切尺寸,还是通过Modifier.fillMaxSize,ColumnScope.weight等相对于父级指定精确尺寸。如果父级包装了此子级,则仅必须指定确切尺寸
2022-11-13

Jetpack Compose常用组件详细介绍

本篇开始介绍Jetpack Compose 中常用的组件。有一部分之前的文章中也出现过,今天详细说明一下
2022-11-13

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录