Compose 5 个简短动画,让您的应用脱颖而出

5 quick animations to make your Compose app stand out

浏览 5 个快速动画,让您的应用在短短几分钟内生动起来。

1. AnimatedVisibility()

下面使用简单的 if 语句来显示或隐藏文本。

为了提升 UI 效果,将不断变化的可见状态包装在 AnimatedVisibility 组合中,使得文本的显示或隐藏带有动画效果。

kotlin 复制代码
@Composable
public fun AnimatedVisibility(
    visible: Boolean,
    modifier: Modifier = Modifier,
    enter: EnterTransition = fadeIn() + expandIn(),
    exit: ExitTransition = shrinkOut() + fadeOut(),
    label: String = "AnimatedVisibility",
    content: @Composable() AnimatedVisibilityScope.() -> Unit,
) {
    val transition = updateTransition(visible, label)
    AnimatedVisibilityImpl(transition, { it }, modifier, enter, exit, content = content)
}

AnimatedVisibility 还有一系列不同的自定义选项。

2. Modifier.animateContentSize()

通过更改 Text 在屏幕上绘制的最大行数,单击文本时切换展开状态,

我们可以使用 Modifier 轻松修复这种跳跃状态。只需要将 animateContentSize() 添加到 Modifier 链中,即可获得即时平滑的变化。

kotlin 复制代码
public fun Modifier.animateContentSize(
    animationSpec: FiniteAnimationSpec<IntSize> =
        spring(
            stiffness = Spring.StiffnessMediumLow,
            visibilityThreshold = IntSize.VisibilityThreshold,
        ),
    finishedListener: ((initialValue: IntSize, targetValue: IntSize) -> Unit)? = null,
): Modifier =
    this.clipToBounds() then
        SizeAnimationModifierElement(animationSpec, Alignment.TopStart, finishedListener)

如果想让动画变得更有弹性,可以更改 animateContentSize() 修饰符以接受动画规范。 大多数动画 API 都提供设置动画规范的功能,可以使用它来定义动画如何发生。

下面给动画添加弹簧规范,将刚度 stiffness 设置为低,并添加少量的弹跳 dampingRatio 为 DampingRatioLowBouncy。我们可以看到动画拥有了弹跳的效果。

3. AnimatedContent()

通过选择多 Tab 中的选项,来切换不同的组合内容。此时的内容切换十分生硬,内容之间没有任何的平滑过渡。

将切换内容代码包装在 AnimatedContent 组合中,提供将要转换到的目标状态。现在不同组合项之间的切换具有淡入淡出和相互缩放的效果,比之前好多了。

kotlin 复制代码
@Composable
public fun <S> AnimatedContent(
    targetState: S,
    modifier: Modifier = Modifier,
    transitionSpec: AnimatedContentTransitionScope<S>.() -> ContentTransform = {
        (fadeIn(animationSpec = tween(220, delayMillis = 90)) +
                scaleIn(initialScale = 0.92f, animationSpec = tween(220, delayMillis = 90)))
            .togetherWith(fadeOut(animationSpec = tween(90)))
    },
    contentAlignment: Alignment = Alignment.TopStart,
    label: String = "AnimatedContent",
    contentKey: (targetState: S) -> Any? = { it },
    content: @Composable() AnimatedContentScope.(targetState: S) -> Unit,
) {
    val transition = updateTransition(targetState = targetState, label = label)
    transition.AnimatedContent(
        modifier,
        transitionSpec,
        contentAlignment,
        contentKey,
        content = content,
    )
}

通过更改 AnimatedContent 的过渡规范,我们可以自定义屏幕上出现的的新可组合项如何进入屏幕以及旧可组合项如何退出屏幕。

使用 slideIntoContainer 将新内容向上滑动进入,使用 slideOutOfContainer 将旧内容向下滑动退出。我们还通过 animationSpec 设置动画的持续时间和缓动效果。

4. animateFloatAsState()

进度条计算进度并更新展示,这样的变化十分生硬,缺少平滑过渡。

使用 animateFloatAsState() 动态计算进度,使得进度条的变化产生动画效果。

kotlin 复制代码
@Composable
public fun animateFloatAsState(
    targetValue: Float,
    animationSpec: AnimationSpec<Float> = defaultAnimation,
    visibilityThreshold: Float = 0.01f,
    label: String = "FloatAnimation",
    finishedListener: ((Float) -> Unit)? = null,
): State<Float> {
    val resolvedAnimSpec =
        if (animationSpec === defaultAnimation) {
            remember(visibilityThreshold) { spring(visibilityThreshold = visibilityThreshold) }
        } else {
            animationSpec
        }
    return animateValueAsState(
        targetValue,
        Float.VectorConverter,
        resolvedAnimSpec,
        visibilityThreshold,
        label,
        finishedListener,
    )
}

5. rememberInfiniteTransition() with Custom DrawScope drawing

实现自定义彩虹边框,颜色围绕着图像轮廓旋转。这里需要使用无限执行的动画。

  • 使用 rememberInfiniteTransition() 创建一个无限动画 InfiniteTransition 声明为 infiniteTransition。
kotlin 复制代码
@Composable
public fun rememberInfiniteTransition(label: String = "InfiniteTransition"): InfiniteTransition {
    val infiniteTransition = remember { InfiniteTransition(label) }
    infiniteTransition.run()
    return infiniteTransition
}
  • 调用 infiniteTransition.animateFloat() 创建一个动态变化的 State 声明为 rotationAnimation。
kotlin 复制代码
@Composable
public fun InfiniteTransition.animateFloat(
    initialValue: Float,
    targetValue: Float,
    animationSpec: InfiniteRepeatableSpec<Float>,
    label: String = "FloatAnimation",
): State<Float> =
    animateValue(initialValue, targetValue, Float.VectorConverter, animationSpec, label)
  • 在 Image 的 Modifier.drawBehind{} 代码块中调用 rotate() 方法,参数 degrees 角度传入上一步声明的 rotationAnimation。
kotlin 复制代码
/** Draw into a [Canvas] behind the modified content. */
fun Modifier.drawBehind(onDraw: DrawScope.() -> Unit) = this then DrawBehindElement(onDraw)

inline fun DrawScope.rotate(degrees: Float, pivot: Offset = center, block: DrawScope.() -> Unit) =
    withTransform({ rotate(degrees, pivot) }, block)
  • 如此在绘制彩虹边框背景的时候,边框会不停地围绕图像旋转。

infiniteRepeatable()

创建一个无限重复动画规格

kotlin 复制代码
@Stable
public fun <T> infiniteRepeatable(
    animation: DurationBasedAnimationSpec<T>,
    repeatMode: RepeatMode = RepeatMode.Restart,
    initialStartOffset: StartOffset = StartOffset(0),
): InfiniteRepeatableSpec<T> = InfiniteRepeatableSpec(animation, repeatMode, initialStartOffset)
相关推荐
Android小码家14 小时前
framework&framework-minus-apex&android.jar的区别
android·python·jar
技术风向解码者14 小时前
安卓跨端选型:为什么优先看 Kuikly
android
科小怪14 小时前
大肥鱼桌宠下载(2026最新版):在安卓桌面上养一条会走会弹会碎碎念的胖鱼
android
qq36219670514 小时前
安卓安装包完整性校验:怎么确认下载的 APK 没被动过手脚
android
FLJwu14 小时前
《运动相机硬件防护选型实战》专栏|第二篇(PPTC 自恢复保险丝)
android·经验分享·数码相机·1024程序员节·运动相机
驰骋工作流1 天前
流程时效考核的表结构:从待办时限到 WF_CH 考核结果驰骋BPM驰骋低代码低代码工作流引擎
android·低代码·rxjava
传奇开心果编程1 天前
【Flutter踩坑排雷】第7课:巨型 build 函数坑|全部 UI 写在同一个 build,维护难、隐性异常
android·flutter·ios·移动开发·跨平台·dart·声明式ui
方白羽1 天前
Android 双开环境底层剖析与风控检测落地
android·安全·app
weixin_563371471 天前
Android Studio 2024 版 Device Explorer 打开方法
android·ide·android studio
AIsoft_86891 天前
职场音频文件怎么整理?录音APP有哪些用法
android·音视频