everyone. I have a flip-animation while clicking button (It works fine.). However, when I wrap it with futurebuilder
, my widget will show in the new state without animation after clicking button (The status is right). It really confuses me. My animation disappear! Is there anyway to renew the widget after the animation is finished?
Here is my code
return FutureBuilder(
future: _UIsetting(),
builder: (BuildContext context, AsyncSnapshot<void> snapshot){
if(snapshot.connectionState==ConnectionState.done){
return Container(
//flip animation
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) {
final isUnder = (ValueKey(flip) != widget);
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'),
),
),
//determine clicking which button(if T, click Button1)
flip?
Row(
children: [
ElevatedButton(
onPressed: (){
setState(() {
_flipCheck();
});
},
child:Text("button1"),
),
ElevatedButton(
onPressed: (){},
child:Text("button2"),
),
],
):
Row(
children: [
ElevatedButton(
onPressed: (){},
child:Text("button1"),
),
ElevatedButton(
onPressed: (){
setState(() {
_flipCheck();
});
},
child:Text("button2"),
),
],
)
);
}else{
return const CircularProgressIndicator();
}
}
);
Here for _UIsetting
Future _UIsetting() async{
SharedPreferences prefs = await SharedPreferences.getInstance();
flip=prefs.getBool('flip')!; //condition
print("_UIsetting flip $flip");
id=prefs.getString("ID").toString(); //user id
}
@override
void initState() {
super.initState();
_UIsetting();
}
Here for _flipCheck
Future _flipCheck() async{
SharedPreferences prefs = await SharedPreferences.getInstance();
now=DateTime.now().millisecondsSinceEpoch;
if((now-previous)~/3600000>=7){
//update time (in local)
flip=true;
prefs.setBool('flip', true);
//upload data (in DB)
_upload();
}else{
flip=false;
prefs.setBool('flip', false);
}
}
All code is in class myappState extends State<myapp>{}
. I am deeply appreciative of all your feedback.
Using future function in future builder is a bad usage. When widget tree building your future functions runs every time, then your async task happens again. So you have to create a Future object in class and assign its value in initState with your future function.
create the future object in class:
Future<String>? idFuture;
assign the future value instead of only call the funciton:
@override
void initState() {
super.initState();
idFuture = _UIsetting();
}
make _IUSetting function returns Future of String:
Future<String> _UIsetting() async {
...
return prefs.getString("ID").toString(); //user id
}
When using FutureBuilder create FutureBuilder with the future object:
FutureBuilder<String>(
future: idFuture,
builder: (_, snapshot) {
if (snapshot.hasData) {
final String id = snapshot.data; // your id variable here
}
}
),
I could not run your code, so I am not sure about the solution. But anyway the usage of futures in Future builders should be like that.