AnimationBuilder 和 FutureBuilder - 如何在未来 returns 和构建之后执行动画?
AnimationBuilder with FutureBuilder - How to execute animation after future returns and builds?
我正在调用 api 来获取一些数据,然后我想在(从底部)显示它的小部件中设置动画。每部分的代码都是单独工作的,但我似乎无法弄清楚在 FutureBuilder 从其构建器函数返回后如何执行动画?我在哪里或如何调用 cardController.forward()
?
Widget mapCard(Area area) {
return Align(
alignment: Alignment.bottomCenter,
child: AnimatedBuilder(
builder: (BuildContext context, Widget child) {
return InkWell(
onTap: () {
Navigator.of(context).push(_createHeroRoute(area));
},
child: Container(
margin: cardMargin.value,
width: 300,
height: 150,
child: Hero(
tag: 'location',
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
width: 274,
height: 150,
child: Image.network(area.images[0].url,
fit: BoxFit.cover)),
Align(
alignment: Alignment.centerRight,
child: Container(
height: 150,
//30, 42, 65
// 412A1E
decoration: new BoxDecoration(
color: Color.fromARGB(255, 30, 42, 65),
),
child:
Icon(Icons.arrow_right, color: Colors.white))),
],
),
),
),
);
},
animation: cardController,
),
);
}
在构建堆栈中:
FutureBuilder(
future: fArea,
builder: (context, AsyncSnapshot<Area> snap) {
if (snap.hasData) {
return mapCard(snap.data);
} else {
return Text('here');
}
})
您可以复制粘贴 运行 下面的完整代码
您可以将 MapCard
设为 StatefulWidget
并在 initState
中调用 cardController.forward
@override
void initState() {
super.initState();
cardController =
AnimationController(duration: const Duration(seconds: 10), vsync: this);
animation = Tween<double>(begin: 0, end: -300.0).animate(cardController)
..addStatusListener((state) => print('$state'));
cardController.forward();
}
工作演示
完整代码
import 'package:flutter/material.dart';
import 'dart:math' as math;
class MapCard extends StatefulWidget {
Area area;
MapCard(Area data, {Key key}) : super(key: key);
@override
_MapCardState createState() => _MapCardState();
}
class _MapCardState extends State<MapCard> with TickerProviderStateMixin {
AnimationController cardController;
Animation<double> animation;
@override
void initState() {
super.initState();
cardController =
AnimationController(duration: const Duration(seconds: 10), vsync: this);
animation = Tween<double>(begin: 0, end: -300.0).animate(cardController)
..addStatusListener((state) => print('$state'));
cardController.forward();
}
@override
void dispose() {
cardController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Align(
alignment: AlignmentDirectional.bottomCenter,
child: AnimatedBuilder(
animation: cardController,
child: InkWell(
onTap: () {
//Navigator.of(context).push(_createHeroRoute(area));
},
child: Container(
//margin: cardMargin.value,
width: 300,
height: 150,
child: Hero(
tag: 'location',
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
width: 274,
height: 150,
child: Image.network("https://picsum.photos/250?image=9",
fit: BoxFit.cover)),
Align(
alignment: Alignment.centerRight,
child: Container(
height: 150,
//30, 42, 65
// 412A1E
decoration: new BoxDecoration(
color: Color.fromARGB(255, 30, 42, 65),
),
child: Icon(Icons.arrow_right, color: Colors.white))),
],
),
),
),
),
builder: (BuildContext context, Widget child) {
return Transform.translate(
offset: Offset(0, animation.value),
child: child,
);
},
),
);
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class Area {
String data;
Area(this.data);
}
class _MyHomePageState extends State<MyHomePage> {
Future<Area> fArea;
Future<Area> getArea() async {
await Future.delayed(Duration(seconds: 3), () {});
return Future.value(Area("data"));
}
@override
void initState() {
fArea = getArea();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: FutureBuilder(
future: fArea,
builder: (context, AsyncSnapshot<Area> snap) {
switch (snap.connectionState) {
case ConnectionState.none:
return Text('none');
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
case ConnectionState.active:
return Text('');
case ConnectionState.done:
if (snap.hasData) {
return MapCard(snap.data);
} else {
return Center(child: CircularProgressIndicator());
}
}
}));
}
}
我正在调用 api 来获取一些数据,然后我想在(从底部)显示它的小部件中设置动画。每部分的代码都是单独工作的,但我似乎无法弄清楚在 FutureBuilder 从其构建器函数返回后如何执行动画?我在哪里或如何调用 cardController.forward()
?
Widget mapCard(Area area) {
return Align(
alignment: Alignment.bottomCenter,
child: AnimatedBuilder(
builder: (BuildContext context, Widget child) {
return InkWell(
onTap: () {
Navigator.of(context).push(_createHeroRoute(area));
},
child: Container(
margin: cardMargin.value,
width: 300,
height: 150,
child: Hero(
tag: 'location',
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
width: 274,
height: 150,
child: Image.network(area.images[0].url,
fit: BoxFit.cover)),
Align(
alignment: Alignment.centerRight,
child: Container(
height: 150,
//30, 42, 65
// 412A1E
decoration: new BoxDecoration(
color: Color.fromARGB(255, 30, 42, 65),
),
child:
Icon(Icons.arrow_right, color: Colors.white))),
],
),
),
),
);
},
animation: cardController,
),
);
}
在构建堆栈中:
FutureBuilder(
future: fArea,
builder: (context, AsyncSnapshot<Area> snap) {
if (snap.hasData) {
return mapCard(snap.data);
} else {
return Text('here');
}
})
您可以复制粘贴 运行 下面的完整代码
您可以将 MapCard
设为 StatefulWidget
并在 initState
cardController.forward
@override
void initState() {
super.initState();
cardController =
AnimationController(duration: const Duration(seconds: 10), vsync: this);
animation = Tween<double>(begin: 0, end: -300.0).animate(cardController)
..addStatusListener((state) => print('$state'));
cardController.forward();
}
工作演示
完整代码
import 'package:flutter/material.dart';
import 'dart:math' as math;
class MapCard extends StatefulWidget {
Area area;
MapCard(Area data, {Key key}) : super(key: key);
@override
_MapCardState createState() => _MapCardState();
}
class _MapCardState extends State<MapCard> with TickerProviderStateMixin {
AnimationController cardController;
Animation<double> animation;
@override
void initState() {
super.initState();
cardController =
AnimationController(duration: const Duration(seconds: 10), vsync: this);
animation = Tween<double>(begin: 0, end: -300.0).animate(cardController)
..addStatusListener((state) => print('$state'));
cardController.forward();
}
@override
void dispose() {
cardController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Align(
alignment: AlignmentDirectional.bottomCenter,
child: AnimatedBuilder(
animation: cardController,
child: InkWell(
onTap: () {
//Navigator.of(context).push(_createHeroRoute(area));
},
child: Container(
//margin: cardMargin.value,
width: 300,
height: 150,
child: Hero(
tag: 'location',
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
width: 274,
height: 150,
child: Image.network("https://picsum.photos/250?image=9",
fit: BoxFit.cover)),
Align(
alignment: Alignment.centerRight,
child: Container(
height: 150,
//30, 42, 65
// 412A1E
decoration: new BoxDecoration(
color: Color.fromARGB(255, 30, 42, 65),
),
child: Icon(Icons.arrow_right, color: Colors.white))),
],
),
),
),
),
builder: (BuildContext context, Widget child) {
return Transform.translate(
offset: Offset(0, animation.value),
child: child,
);
},
),
);
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class Area {
String data;
Area(this.data);
}
class _MyHomePageState extends State<MyHomePage> {
Future<Area> fArea;
Future<Area> getArea() async {
await Future.delayed(Duration(seconds: 3), () {});
return Future.value(Area("data"));
}
@override
void initState() {
fArea = getArea();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: FutureBuilder(
future: fArea,
builder: (context, AsyncSnapshot<Area> snap) {
switch (snap.connectionState) {
case ConnectionState.none:
return Text('none');
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
case ConnectionState.active:
return Text('');
case ConnectionState.done:
if (snap.hasData) {
return MapCard(snap.data);
} else {
return Center(child: CircularProgressIndicator());
}
}
}));
}
}