如何使用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
相关产品推荐
相关产品推荐

