从Composable获取坐标在Canvas绘制RectF位置偏移问题
问题背景
通过.onGloballyPositioned修饰符获取Box组件的布局坐标,实现视图高亮效果,初始坐标获取代码:
val viewLeft = layoutCoordinates.boundsInWindow().left val viewTop = layoutCoordinates.boundsInWindow().top val viewRight = layoutCoordinates.boundsInWindow().right val viewBottom = layoutCoordinates.boundsInWindow().bottom
在Canvas中使用上述坐标绘制高亮圆角矩形时,绘制结果始终存在固定位置偏移,绘制代码如下:
canvas.drawRoundRect( viewLeft, viewTop, viewRight, viewBottom, cornerRadius, cornerRadius, paint )
实际运行效果:
错误原因
核心问题是坐标参考系不匹配:
boundsInWindow()返回的是组件相对于整个应用窗口的坐标,原点在窗口左上角- Canvas的绘制坐标系原点是Canvas自身的左上角,和窗口原点存在固定偏移,偏移值等于Canvas本身在窗口中的位置坐标
直接使用窗口坐标系的坐标在Canvas上绘制,就会产生和偏移值完全一致的位置错位。
修复方法
两种方案任选其一即可:
- 方案1:坐标换算
给承载绘制逻辑的Canvas也添加.onGloballyPositioned修饰符,拿到Canvas自身在窗口中的位置,将目标Box的窗口坐标转换为Canvas的局部绘制坐标后再绘制:// 从Canvas的onGloballyPositioned回调中获取canvasLayoutCoordinates val canvasOffsetX = canvasLayoutCoordinates.boundsInWindow().left val canvasOffsetY = canvasLayoutCoordinates.boundsInWindow().top // 换算得到Canvas局部坐标系下的绘制坐标 val drawLeft = viewLeft - canvasOffsetX val drawTop = viewTop - canvasOffsetY val drawRight = viewRight - canvasOffsetX val drawBottom = viewBottom - canvasOffsetY canvas.drawRoundRect( drawLeft, drawTop, drawRight, drawBottom, cornerRadius, cornerRadius, paint ) - 方案2:统一使用父容器参考系
如果高亮Canvas和目标Box处于同一个父Composable容器下,直接调用layoutCoordinates.boundsInParent()获取Box相对于共同父容器的坐标,只要保证Canvas的布局和Box参考同一个父容器坐标系,直接用该坐标绘制就不会出现偏移。
内容的提问来源于stack exchange,提问作者Ilyas Saleem Khurshid
相关产品推荐
相关产品推荐

