Flutter中FutureBuilder包裹AnimatedSwitcher后动画消失问题求助
问题原因
你的问题出在FutureBuilder的使用方式上:
- 每次调用
setState时,FutureBuilder会重新执行传入的_UIsetting()方法,该方法会从SharedPreferences重新读取flip值,直接覆盖当前状态,导致AnimatedSwitcher的动画还没完成就被强制切换。 FutureBuilder的future参数直接传入_UIsetting(),会在每次组件build时创建新的Future实例,触发不必要的异步操作,打断动画流程。
解决方案
移除FutureBuilder,改用状态变量管理加载状态,初始化操作只在initState中执行一次,后续状态更新直接操作本地变量并触发setState:
修改后的完整代码
import 'dart:math'; import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; class myappState extends State<myapp> { bool flip = false; String id = ""; int previous = 0; // 假设你已定义该变量 bool isLoading = true; // 新增加载状态变量 @override void initState() { super.initState(); _UIsetting(); } Future _UIsetting() async { SharedPreferences prefs = await SharedPreferences.getInstance(); flip = prefs.getBool('flip') ?? false; // 添加空值判断,避免空指针 print("_UIsetting flip $flip"); id = prefs.getString("ID") ?? ""; setState(() { isLoading = false; // 初始化完成后关闭加载状态 }); } Future _flipCheck() async { SharedPreferences prefs = await SharedPreferences.getInstance(); int now = DateTime.now().millisecondsSinceEpoch; if ((now - previous) ~/ 3600000 >= 7) { flip = true; await prefs.setBool('flip', true); _upload(); } else { flip = false; await prefs.setBool('flip', false); } setState(() {}); // 修改flip后直接触发状态更新 } @override Widget build(BuildContext context) { if (isLoading) { return const CircularProgressIndicator(); } return Container( child: Column( children: [ // 翻转动画 AnimatedSwitcher( duration: const Duration(seconds: 1), transitionBuilder: (Widget widget, Animation<double> animation) { final rotateAnim = Tween(begin: pi, end: 0.0).animate(animation); return AnimatedBuilder( animation: rotateAnim, child: widget, builder: (context, widget) { // 修正判断逻辑,对比widget的key与当前flip对应的目标key final targetKey = ValueKey(flip ? 0 : 1); final isUnder = (widget?.key != targetKey); final value = isUnder ? min(rotateAnim.value, pi / 2) : rotateAnim.value; return Transform( transform: Matrix4.rotationY(value), alignment: Alignment.center, child: widget, ); }, ); }, child: flip ? Container( key: const ValueKey(0), width: MediaQuery.of(context).size.width, margin: const EdgeInsets.symmetric(horizontal: 30), child: Image.asset('assets/work1.png'), ) : Container( key: const ValueKey(1), width: MediaQuery.of(context).size.width, margin: const EdgeInsets.symmetric(horizontal: 30), child: Image.asset('assets/work2.png'), ), ), // 根据flip状态切换按钮可点击状态 flip ? Row( children: [ ElevatedButton( onPressed: _flipCheck, // 直接调用方法,无需嵌套setState child: const Text("button1"), ), ElevatedButton( onPressed: () {}, child: const Text("button2"), ), ], ) : Row( children: [ ElevatedButton( onPressed: () {}, child: const Text("button1"), ), ElevatedButton( onPressed: _flipCheck, child: const Text("button2"), ), ], ) ], ), ); } void _upload() { // 你的数据上传逻辑 } } // 对应的StatelessWidget(示例) class myapp extends StatefulWidget { const myapp({super.key}); @override myappState createState() => myappState(); }
关键修改点
- 移除FutureBuilder:用
isLoading状态变量控制加载状态,初始化完成后再显示主内容,避免重复触发异步操作打断动画。 - 修正状态更新逻辑:
_flipCheck中修改flip后直接调用setState,不再依赖重新读取SharedPreferences,确保动画能完整执行。 - 优化动画判断逻辑:调整
AnimatedSwitcher中isUnder的判断条件,保证动画触发逻辑准确。 - 空值安全处理:读取SharedPreferences值时添加空值判断,避免空指针异常。
内容的提问来源于stack exchange,提问作者CindyLee
相关产品推荐
相关产品推荐

