You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetpack Compose矢量平移动画新版本库适配问题及优化方案咨询

Jetpack Compose 无限平移动画适配新版本问题及优化方案

问题描述

在Jetpack Compose应用中实现的无限循环矢量平移动画,在drawablepainter 0.33.2及Compose 1.5.4版本下可正常运行,但升级至drawablepainter 0.34.0或Compose 1.6.0后,动画仅显示初始帧,无日志报错。

原实现代码

@Composable
fun GarageIndicatorClosing() {
    val backgroundVector =
        ImageVector.vectorResource(id = R.drawable.garage_door_open)
    val garageBackgroundPainter = rememberVectorPainter(image = backgroundVector)

    var yState by remember { mutableIntStateOf(0) }
    val yOffset = animateIntAsState(
        targetValue = yState,
        animationSpec =
        infiniteRepeatable(animation = tween(durationMillis = 1200, easing = LinearEasing))
    )
    Box {
        Image(painter = garageBackgroundPainter, contentDescription = null)
        MoveGarageArrow(yOffset = yOffset.value) {
            GarageArrow(arrowID = R.drawable.garage_door_closing_arrow_anim)
        }
    }
    yState = 150
}

@Composable
fun GarageArrow(arrowID: Int) {
    Image(
        painter = painterResource(id = arrowID),
        contentDescription = null,
        contentScale = ContentScale.Crop
    )
}

@Composable
fun MoveGarageArrow(
    yOffset: Int,
    item: @Composable () -> Unit
) {
    Box {
        Box(
            Modifier
                .absoluteOffset(y = yOffset.dp)
                .align(Alignment.Center)
        ) {
            item()
        }
    }
}

矢量资源文件

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="200dp"
    android:height="60dp"
    android:viewportWidth="150"
    android:viewportHeight="45">
  <path
      android:pathData="M30.05,3.13 L75.8,41.88 121.55,3.13h-16L76.05,27.63 45.55,3.13Z"
      android:strokeLineJoin="miter"
      android:strokeWidth="1"
      android:fillColor="#00ff00"
      android:strokeColor="#ffffff"
      android:strokeLineCap="butt"/>
</vector>

原依赖配置(可正常运行)

dependencies {
    implementation "androidx.activity:activity-compose:1.8.2"
    implementation "androidx.car.app:app:1.2.0"
    implementation "androidx.compose.animation:animation-graphics:1.5.4"
    implementation "androidx.compose.foundation:foundation:1.5.4"
    implementation "androidx.compose.ui:ui-tooling-preview:1.5.4"
    implementation "androidx.compose.material3:material3:1.1.2"
    implementation "androidx.constraintlayout:constraintlayout:2.1.4"
    implementation "androidx.core:core-ktx:1.12.0"
    implementation "androidx.preference:preference-ktx:1.2.1"
    implementation "androidx.work:work-runtime-ktx:2.9.0"
    implementation "com.android.volley:volley:1.2.1"
    implementation 'com.google.accompanist:accompanist-drawablepainter:0.33.1-alpha'
    implementation "com.google.android.gms:play-services-location:21.1.0"
    api 'com.google.android.material:material:1.11.0'
    implementation 'com.google.code.gson:gson:2.10.1'

    apply plugin: 'com.google.gms.google-services'
    debugImplementation 'androidx.compose.ui:ui-tooling:1.5.4'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
}

优化后的动画实现方案

针对新版本Compose的重组机制和drawablepainter库的变化,调整实现逻辑如下:

核心优化点

  • 避免在Composable根作用域直接修改状态变量,改用动画系统原生逻辑触发循环
  • 使用animateFloatAsState替代animateIntAsState,适配Compose动画系统的浮点型偏好,提升流畅度
  • 简化布局嵌套,直接通过Modifier实现偏移与对齐,减少重组开销
  • 明确动画重复模式,确保无限循环逻辑稳定

优化后代码

@Composable
fun GarageIndicatorClosing() {
    val backgroundVector = ImageVector.vectorResource(id = R.drawable.garage_door_open)
    val garageBackgroundPainter = rememberVectorPainter(image = backgroundVector)

    // 直接以目标值初始化浮点型动画,配合无限循环配置
    val animateOffset by animateFloatAsState(
        targetValue = 150f,
        animationSpec = infiniteRepeatable(
            animation = tween(durationMillis = 1200, easing = LinearEasing),
            repeatMode = RepeatMode.Restart
        ),
        label = "garage_arrow_animation"
    )

    Box {
        Image(
            painter = garageBackgroundPainter,
            contentDescription = "Garage door background"
        )
        
        // 直接在箭头组件上应用偏移和对齐,简化布局层级
        Image(
            painter = painterResource(id = R.drawable.garage_door_closing_arrow_anim),
            contentDescription = "Closing arrow",
            contentScale = ContentScale.Crop,
            modifier = Modifier
                .align(Alignment.Center)
                .offset(y = animateOffset.dp)
        )
    }
}

适配新版本的依赖调整

升级到Compose 1.6.0及drawablepainter 0.34.0时,确保依赖版本匹配:

dependencies {
    implementation "androidx.activity:activity-compose:1.8.2"
    implementation "androidx.car.app:app:1.2.0"
    // 升级Compose核心库到1.6.0
    implementation "androidx.compose.animation:animation-graphics:1.6.0"
    implementation "androidx.compose.foundation:foundation:1.6.0"
    implementation "androidx.compose.ui:ui-tooling-preview:1.6.0"
    implementation "androidx.compose.material3:material3:1.2.0"
    implementation "androidx.constraintlayout:constraintlayout:2.1.4"
    implementation "androidx.core:core-ktx:1.12.0"
    implementation "androidx.preference:preference-ktx:1.2.1"
    implementation "androidx.work:work-runtime-ktx:2.9.0"
    implementation "com.android.volley:volley:1.2.1"
    // 升级drawablepainter到0.34.0
    implementation 'com.google.accompanist:accompanist-drawablepainter:0.34.0'
    implementation "com.google.android.gms:play-services-location:21.1.0"
    api 'com.google.android.material:material:1.11.0'
    implementation 'com.google.code.gson:gson:2.10.1'

    apply plugin: 'com.google.gms.google-services'
    debugImplementation 'androidx.compose.ui:ui-tooling:1.6.0'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
}

方案说明

  1. 状态逻辑优化:移除了原代码中直接修改状态变量的写法,利用animateFloatAsState的原生配置实现无限循环,避免重组时的状态干扰。
  2. 动画流畅度提升:浮点型动画与Modifier.offset的参数类型一致,避免类型转换开销,适配Compose动画系统的底层优化。
  3. 布局简化:删除了冗余的嵌套组件和封装函数,直接在目标Image上应用修饰符,减少布局层级与重组消耗。

内容的提问来源于stack exchange,提问作者80sTron

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 17:51:00