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

使用Cubit实现Widget动画切换:Widget已重建但动画未生效

AnimatedSwitcher结合Cubit时动画不生效的解决方法

问题背景

我希望通过Cubit替代setState更新目标Widget(仅重建该特定Widget),但目前Widget能正常切换内容,AnimatedSwitcher的过渡动画却完全不生效。以下是我原本的代码实现:

原UI代码

final _animationCubit = AnimationCubit();

// ...

AnimatedSwitcher(
  duration: const Duration(seconds: 3),
  child: BlocBuilder<AnimationCubit, bool>(
    key: ValueKey(
      _animationCubit.state ? context.l10n.signIn : context.l10n.signOut,
    ),
    bloc: _animationCubit,
    builder: (context, state) {
      return Text(
        state ? context.l10n.signIn : context.l10n.signOut,
        textAlign: TextAlign.center,
        style: context.textTheme.titleLarge?.copyWith(
          color: context.colorScheme.primary,
        ),
        key: ValueKey(
          _animationCubit.state ? 'add_${context.l10n.signIn}' : 'add_${context.l10n.signOut}',
        ),
      );
    },
  ),
)

Cubit实现

import 'package:bloc/bloc.dart';

class AnimationCubit extends Cubit<bool> {
  AnimationCubit() : super(false);

  void isAnimationCompleted(bool isCompleted) => emit(isCompleted);
}

状态触发代码

_animationCubit.isAnimationCompleted(!_animationCubit.state);

问题原因

AnimatedSwitcher的动画触发逻辑是检测直接子Widget的key变化或Widget类型变更。原代码中将BlocBuilder作为AnimatedSwitcher的直接子Widget,状态变化时仅BlocBuilder内部的Text会重建,AnimatedSwitcher的直接子元素始终是同一个BlocBuilder实例(即便给BlocBuilder加了key,这种嵌套结构也不符合AnimatedSwitcher的预期用法),因此动画无法被触发。


修复方案

调整Widget嵌套结构,让BlocBuilder包裹AnimatedSwitcher,确保AnimatedSwitcher的直接子Widget是随状态变化的Text,且Text的key能区分不同状态:

修复后的UI代码

final _animationCubit = AnimationCubit();

// ...

BlocBuilder<AnimationCubit, bool>(
  bloc: _animationCubit,
  builder: (context, state) {
    final displayText = state ? context.l10n.signIn : context.l10n.signOut;
    return AnimatedSwitcher(
      duration: const Duration(seconds: 3),
      child: Text(
        displayText,
        textAlign: TextAlign.center,
        style: context.textTheme.titleLarge?.copyWith(
          color: context.colorScheme.primary,
        ),
        key: ValueKey(displayText), // 用文本内容作为唯一key,状态变化时key自动更新
      ),
    );
  },
)

优化后的Cubit实现

为了方法名更直观,可修改Cubit的状态切换方法:

import 'package:bloc/bloc.dart';

class AnimationCubit extends Cubit<bool> {
  AnimationCubit() : super(false);

  void toggleAuthState() => emit(!state);
}

状态触发代码

_animationCubit.toggleAuthState();

关键说明

  • AnimatedSwitcher必须直接包裹需要切换的Widget(这里是Text),且该Widget的key在状态变化时必须唯一。
  • 不需要给BlocBuilder额外设置key,它仅负责监听Cubit状态并重建内部的AnimatedSwitcher即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 16:47:06