添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

如何用Animatable使Rect位置动画化?

2 人关注

我正在建立一个图像裁剪器。我正在使用矩形来绘制动态叠加。当覆盖物超出图像范围时,当指针上升时,我会将其移回图像范围。

我建造的东西

open var overlayRect: Rect =
    Rect(offset = Offset.Zero, size = Size(size.width.toFloat(), size.height.toFloat()))

我使用这个函数得到最终的位置,并将其移回有效的边界。

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来为一个矩形制作动画?

I checked 动画的正式文件和建议是使用transition和 transition.animateRect从一个状态到另一个状态,但我没有状态,我想从当前的动态值到一个动态目标做动画,这是一个非组合式称为DynamicCropState的类,该类扩展了一个类似于缩放状态 here. Need to animate using Animatable or 非组合式 apis.

android
android-jetpack-compose
jetpack-compose-animation
Thracian
Thracian
发布于 2022-08-31
1 个回答
Thracian
Thracian
发布于 2022-08-31
已采纳
0 人赞同

我解决了这个问题,创建了一个 AnimationVector4D ,在 Float Rect 之间进行转换。

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)

为了演示,创建了一个内部动画的类,并返回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