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

如何使用Bloc实现文本颜色在两种值间的切换与动画效果

用BlocBuilder替代StatefulWidget实现颜色平滑过渡动画

以下是完整实现方案,核心是将动画控制逻辑迁移到Bloc中,通过BlocBuilder结合AnimatedBuilder实现颜色的平滑过渡:

1. 定义Bloc的事件与状态

先创建用于触发动画和传递动画对象的事件与状态:

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:equatable/equatable.dart';

// 触发颜色动画的事件
class StartColorAnimation extends Equatable {
  @override
  List<Object?> get props => [];
}

// 包含颜色动画对象的状态
class ColorAnimationState extends Equatable {
  final Animation<Color> colorAnimation;

  const ColorAnimationState(this.colorAnimation);

  @override
  List<Object?> get props => [colorAnimation];
}

2. 实现Bloc类

在Bloc中管理动画控制器和颜色补间逻辑,处理动画的初始化与触发:

class ColorAnimationBloc extends Bloc<StartColorAnimation, ColorAnimationState> {
  late final AnimationController _controller;
  late final Animation<Color> _colorAnimation;

  ColorAnimationBloc(TickerProvider tickerProvider) : super(ColorAnimationState(const AlwaysStoppedAnimation(Colors.red))) {
    // 初始化动画控制器
    _controller = AnimationController(
      vsync: tickerProvider,
      duration: const Duration(seconds: 5),
    );

    // 创建红色到白色的颜色补间动画
    _colorAnimation = ColorTween(
      begin: Colors.red,
      end: Colors.white,
    ).animate(_controller);

    // 处理触发动画的事件
    on<StartColorAnimation>((event, emit) {
      _controller.forward();
      emit(ColorAnimationState(_colorAnimation));
    });
  }

  @override
  Future<void> close() {
    _controller.dispose();
    return super.close();
  }
}

3. UI层实现

通过BlocProvider提供Bloc实例,使用BlocBuilder获取动画状态,再结合AnimatedBuilder渲染带平滑颜色过渡的文本:

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: _ColorAnimationProvider(),
    );
  }
}

// 用于提供TickerProvider的辅助StatefulWidget
class _ColorAnimationProvider extends StatefulWidget {
  const _ColorAnimationProvider();

  @override
  State<_ColorAnimationProvider> createState() => _ColorAnimationProviderState();
}

class _ColorAnimationProviderState extends State<_ColorAnimationProvider> with SingleTickerProviderStateMixin {
  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (context) => ColorAnimationBloc(this),
      child: const ColorAnimationScreen(),
    );
  }
}

class ColorAnimationScreen extends StatelessWidget {
  const ColorAnimationScreen({super.key});

  @override
  Widget build(BuildContext context) {
    // 触发颜色动画
    context.read<ColorAnimationBloc>().add(StartColorAnimation());

    return Scaffold(
      body: Center(
        child: BlocBuilder<ColorAnimationBloc, ColorAnimationState>(
          builder: (context, state) {
            return AnimatedBuilder(
              animation: state.colorAnimation,
              builder: (context, _) {
                return Text(
                  "HELLO!!!",
                  textScaleFactor: 3,
                  style: TextStyle(color: state.colorAnimation.value),
                );
              },
            );
          },
        ),
      ),
    );
  }
}

为什么不能直接用BlocBuilder切换颜色?

直接通过Bloc状态切换颜色是瞬时变化,没有颜色插值的过程,而结合AnimatedBuilder可以监听动画的每一帧,获取颜色的中间插值,从而实现平滑过渡效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 06:45:37