[英]How to animate Rect position with Animatable?
我正在构建一个图像裁剪器。 我正在使用矩形来绘制动态覆盖。 当覆盖超出图像边界时,当指针向上时,我将其移回图像边界。
我建造的
open var overlayRect: Rect =
Rect(offset = Offset.Zero, size = Size(size.width.toFloat(), size.height.toFloat()))
我得到最终的 position 使用这个 function 移回有效范围
internal fun moveIntoBounds(rectBounds: Rect, rectCurrent: Rect): Rect {
var width = rectCurrent.width
var height = rectCurrent.height
if (width > rectBounds.width) {
width = rectBounds.width
}
if (height > rectBounds.height) {
height = rectBounds.height
}
var rect = Rect(offset = rectCurrent.topLeft, size = Size(width, height))
if (rect.left < rectBounds.left) {
rect = rect.translate(rectBounds.left - rect.left, 0f)
}
if (rect.top < rectBounds.top) {
rect = rect.translate(0f, rectBounds.top - rect.top)
}
if (rect.right > rectBounds.right) {
rect = rect.translate(rectBounds.right - rect.right, 0f)
}
if (rect.bottom > rectBounds.bottom) {
rect = rect.translate(0f, rectBounds.bottom - rect.bottom)
}
return rect
}
并将其设置为指针
override fun onUp(change: PointerInputChange) {
touchRegion = TouchRegion.None
overlayRect = moveIntoBounds(rectBounds, overlayRect)
// Calculate crop rectangle
cropRect = calculateRectBounds()
rectTemp = overlayRect.copy()
}
如何将这个矩形动画化到有效边界? 有没有办法使用 Animatable 为矩形设置动画?
我检查了 animation 的官方文档,并建议使用从一个state到另一个DynamicCropState
的transition
和转换。在此处扩展 class ,如缩放 state 。 需要使用 Animatable 或 non-Composable api 进行动画处理。
我解决了这个问题,创建了一个在Float
和Rect
之间转换的AnimationVector4D
val RectToVector = TwoWayConverter(
convertToVector = { rect: Rect ->
AnimationVector4D(rect.left, rect.top, rect.width, rect.height)
},
convertFromVector = { vector: AnimationVector4D ->
Rect(
offset = Offset(vector.v1, vector.v2),
size = Size(vector.v3, vector.v4)
)
}
)
为了演示,创建了一个 class 以在内部进行动画处理并返回Rect
的当前值
class RectWrapper {
private val animatableRect = Animatable(
Rect(
offset = Offset.Zero,
size = Size(300f, 300f)
),
RectToVector
)
val rect: Rect
get() = animatableRect.value
suspend fun animateRectTo(rect: Rect) {
animatableRect.animateTo(rect)
}
}
以及演示如何使用它
@Composable
private fun AnimateRectWithAnimatable() {
val coroutineScope = rememberCoroutineScope()
val rectWrapper = remember {
RectWrapper()
}
Column(modifier = Modifier.fillMaxSize()) {
Button(
modifier = Modifier
.padding(10.dp)
.fillMaxWidth(),
onClick = {
coroutineScope.launch {
rectWrapper.animateRectTo(
Rect(
topLeft = Offset(200f, 200f),
bottomRight = Offset(800f, 800f)
)
)
}
}
) {
Text("Animate")
}
Canvas(
modifier = Modifier
.fillMaxSize()
) {
drawRect(
color = Color.Red,
topLeft = rectWrapper.rect.topLeft,
size = rectWrapper.rect.size
)
}
}
}
如果您希望从 class 为Rect
设置动画,您可以按上述方式实现它。 我通常将这些类作为State
传递给修饰符,并观察并触发Modifier.composed
内部的更改,并将结果返回给使用该修饰符的任何 class。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.