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

如何使用GetX构建带动画的启动屏?解决动画值更新问题

在GetX中实现启动屏动画的正确方式

问题根源

你当前的GetX控制器代码存在一个关键错误:把CurvedAnimation转成.obs后直接取.value赋值给animation,相当于丢掉了它的可观察特性,导致调用update()也无法触发UI刷新。

正确实现方案

方案一:用RxAnimation简化响应式动画(推荐)

GetX自带RxAnimation,可以自动监听动画值变化,无需手动处理监听器:

class SplashScreenViewModel extends GetxController
    with GetSingleTickerProviderStateMixin {
  late AnimationController animationController;
  late RxAnimation<double> animation;

  @override
  void onInit() {
    animationInitilization();
    super.onInit();
  }

  void animationInitilization() {
    animationController = AnimationController(
      vsync: this,
      duration: const Duration(seconds: 2),
    );
    // 用RxAnimation包装动画,自动响应值变化
    animation = RxAnimation<double>(
      CurvedAnimation(
        parent: animationController,
        curve: Curves.easeOut,
      ),
    );
    animationController.forward();
  }

  @override
  void onClose() {
    animationController.dispose(); // 必须销毁控制器,避免内存泄漏
    super.onClose();
  }
}

对应的UI代码需要用Obx包裹动画Widget,确保UI自动刷新:

class SplashScreen extends StatelessWidget {
  const SplashScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final splashVM = Get.put(SplashScreenViewModel());
    return Scaffold(
      body: Stack(
        fit: StackFit.expand,
        children: [
          Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Obx(() => Image.asset(
                'assets/images/logo.png',
                width: splashVM.animation.value * 200,
                height: splashVM.animation.value * 200,
              )),
            ],
          ),
        ],
      ),
    );
  }
}

方案二:手动调用update()配合GetBuilder

如果不想用RxAnimation,修正控制器里的动画初始化逻辑,确保update()能正确通知UI:

class SplashScreenViewModel extends GetxController
    with GetSingleTickerProviderStateMixin {
  late AnimationController animationController;
  late Animation<double> animation;

  @override
  void onInit() {
    animationInitilization();
    super.onInit();
  }

  void animationInitilization() {
    animationController = AnimationController(
      vsync: this,
      duration: const Duration(seconds: 2),
    );
    animation = CurvedAnimation(
      parent: animationController,
      curve: Curves.easeOut,
    );
    // 动画值变化时调用update(),通知GetBuilder刷新UI
    animation.addListener(() => update());
    animationController.forward();
  }

  @override
  void onClose() {
    animationController.dispose();
    super.onClose();
  }
}

对应的UI用GetBuilder监听控制器变化:

class SplashScreen extends StatelessWidget {
  const SplashScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        fit: StackFit.expand,
        children: [
          Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              GetBuilder<SplashScreenViewModel>(
                init: SplashScreenViewModel(),
                builder: (vm) => Image.asset(
                  'assets/images/logo.png',
                  width: vm.animation.value * 200,
                  height: vm.animation.value * 200,
                ),
              ),
            ],
          ),
        ],
      ),
    );
  }
}

核心要点

  • GetX里替代setState()的两种方式:响应式Rx对象+Obx、GetBuilder+update()
  • 不要把Animation转成.obs后直接取.value,这会丢失可观察特性
  • 必须在控制器onClose()中销毁AnimationController,防止内存泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 19:27:32