如何在flutter中使用“动画列表"对最初渲染的项目进行动画处理 [英] How to animate the items rendered initially using Animated List in flutter
问题描述
我在Flutter中使用Animated List来加载列表类,在添加或删除项目时,动画有效,但是在最初加载列表时,动画不起作用.最初加载列表时,是否可以为项目设置动画.
I am using Animated List in flutter to load a list class, while adding or removing the items, the animation works but when the list is initially loaded, the animation does not work. Is there a way to animate items when initially loading the list.
class AnimationTest extends StatefulWidget {
@override
_AnimationTestState createState() => _AnimationTestState();
}
class _AnimationTestState extends State<AnimationTest> with SingleTickerProviderStateMixin {
AnimationController _controller;
@override
void initState() {
_controller = AnimationController(
vsync: this,
duration: const Duration(seconds: 1),
);
super.initState();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AnimatedList(
key: _listKey,
initialItemCount: 3,
itemBuilder: (BuildContext context, int index, Animation animation) {
return SlideTransition(
position: animation.drive(Tween<Offset>(begin: Offset(1.0, 0.0), end: Offset.zero)
.chain(CurveTween(curve: Curves.decelerate))),
child: Row(
children: <Widget>[
Expanded(
child: InkWell(
onTap: () => _listKey.currentState.insertItem(0,duration: Duration(milliseconds: 600)),
child: Container(
padding: EdgeInsets.only(left: 10, right: 10),
height: 100,
child: Card(
margin: EdgeInsets.symmetric(vertical: 4.0),
color: Theme.of(context).backgroundColor,
)),
),
),
],
),
);
},
);
}
}
推荐答案
因为AnimatedList
仅在添加/删除列表中的项目时可以设置动画.您需要使用AnimatedListState
中的insertItem
或removeItem
分别添加每个项目.一种获得良好加载效果的方法是延迟每次插入/删除项目的时间.
Because AnimatedList
can only animate when adding/removing item in the list. You need to add each item individually by using insertItem
or removeItem
from AnimatedListState
. One way to achieve a nice loading effect is to delay each time you insert/remove item.
这里是链接Future
的代码,以便在指定的延迟后将每个项目一个接一个地加载
Here is the code to chain Future
so that each item is loaded one after another after a specified delay
var future = Future(() {});
for (var i = 0; i < fetchedList.length; i++) {
future = future.then((_) {
return Future.delayed(Duration(milliseconds: 100), () {
// add/remove item
});
});
}
从此处可以创建loadItems()
方法,以初始化initState()
中AnimatedList
中的所有项目.记住要同时更新基础数据结构(_listItems
)和AnimatedList
本身,以使其正常工作.
From there you can create a loadItems()
method to initialize all items in the AnimatedList
in initState()
. Remember to update both the underlying data structure (_listItems
) and AnimatedList
itself for it to work.
var _listItems = <Widget>[];
final GlobalKey<AnimatedListState> _listKey = GlobalKey();
@override
void initState() {
super.initState();
_loadItems();
}
void _loadItems() {
// fetching data from web api, local db...
final fetchedList = [
ListTile(
title: Text('Economy'),
trailing: Icon(Icons.directions_car),
),
ListTile(
title: Text('Comfort'),
trailing: Icon(Icons.motorcycle),
),
ListTile(
title: Text('Business'),
trailing: Icon(Icons.flight),
),
];
var future = Future(() {});
for (var i = 0; i < fetchedList.length; i++) {
future = future.then((_) {
return Future.delayed(Duration(milliseconds: 100), () {
_listItems.add(fetchedList[i]);
_listKey.currentState.insertItem(i);
});
});
}
}
这是完整的示例.我在应用栏中添加了2个按钮,以便您可以播放动画
This is the complete example. I added 2 buttons in the app bar so you can play around with the animations
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'YourAwesomeApp',
home: PageWithAnimatedList(),
);
}
}
class PageWithAnimatedList extends StatefulWidget {
@override
_PageWithAnimatedListState createState() => _PageWithAnimatedListState();
}
class _PageWithAnimatedListState extends State<PageWithAnimatedList> {
var _listItems = <Widget>[];
final GlobalKey<AnimatedListState> _listKey = GlobalKey();
@override
void initState() {
super.initState();
_loadItems();
}
void _loadItems() {
// fetching data from web api, db...
final fetchedList = [
ListTile(
title: Text('Economy'),
trailing: Icon(Icons.directions_car),
),
ListTile(
title: Text('Comfort'),
trailing: Icon(Icons.motorcycle),
),
ListTile(
title: Text('Business'),
trailing: Icon(Icons.flight),
),
];
var future = Future(() {});
for (var i = 0; i < fetchedList.length; i++) {
future = future.then((_) {
return Future.delayed(Duration(milliseconds: 100), () {
_listItems.add(fetchedList[i]);
_listKey.currentState.insertItem(_listItems.length - 1);
});
});
}
}
void _unloadItems() {
var future = Future(() {});
for (var i = _listItems.length - 1; i >= 0; i--) {
future = future.then((_) {
return Future.delayed(Duration(milliseconds: 100), () {
final deletedItem = _listItems.removeAt(i);
_listKey.currentState.removeItem(i,
(BuildContext context, Animation<double> animation) {
return SlideTransition(
position: CurvedAnimation(
curve: Curves.easeOut,
parent: animation,
).drive((Tween<Offset>(
begin: Offset(1, 0),
end: Offset(0, 0),
))),
child: deletedItem,
);
});
});
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: <Widget>[
IconButton(icon: Icon(Icons.add), onPressed: _loadItems),
IconButton(icon: Icon(Icons.remove), onPressed: _unloadItems)
],
),
body: AnimatedList(
key: _listKey,
padding: EdgeInsets.only(top: 10),
initialItemCount: _listItems.length,
itemBuilder: (context, index, animation) {
return SlideTransition(
position: CurvedAnimation(
curve: Curves.easeOut,
parent: animation,
).drive((Tween<Offset>(
begin: Offset(1, 0),
end: Offset(0, 0),
))),
child: _listItems[index],
);
},
),
);
}
}
这篇关于如何在flutter中使用“动画列表"对最初渲染的项目进行动画处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!