AnimatedList
List的动画版。
AnimatedList
中两个关键的属性就是itemBuilder
、initialItemCount
:itemBuilder
是构建AnimatedList
的方法;initialItemCount
是初始构件项目数量。
现在开始使用AnimatedList
:
import 'package:flutter/material.dart;
import 'dart:math';
class AnimatedListRoute extends StatefulWidget{
_AnimatedListRouteState createState() => _AnimatedListRouteState();
}
class _AnimatedListRouteState extends State<AnimatedListRoute>{
final _listKey = GlobalKey<AnimatedListState>();
List<int> _data;
Tween<Offset> _tween = Tween<Offset>(begin: Offset(1,0), end: Offset(0,0));
@override
void initState() {
// TODO: implement initState
super.initState();
_data = [12,34,43,12,54];
}
Widget myListItem(String text, Animation animation) {
return SlideTransition(
position: animation.drive(CurveTween(curve: Curves.bounceOut)).drive(_tween),
child: Container(
margin: EdgeInsets.symmetric(vertical: 10.0),
constraints: BoxConstraints.tight(Size(double.infinity, 70)),
alignment: Alignment.center,
child: Text('$text', style: TextStyle(color: Colors.white),),
color: Colors.primaries[int.parse(text) % Colors.primaries.length],
)
);
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text('AnimatedListState'),
),
body: Stack(
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(horizontal: 20.0),
child: AnimatedList(
key: _listKey,
itemBuilder: (context, index, animation) => myListItem(_data[index].toString(), animation),
initialItemCount: _data.length,
),
),
Positioned(
bottom: 30,
right: 10,
child: FloatingActionButton(
heroTag: 'remove',
onPressed: () {
},
child: Icon(Icons.remove),
),
),
Positioned(
bottom: 30,
right: 70,
child: FloatingActionButton(
heroTag: 'add',
onPressed: () {
},
child: Icon(Icons.add),
),
)
],
)
);
}
}
效果
现在点击下方的添加、删除按钮是没有任何响应的,接下来我们为添加按钮添加事件,当点击添加按钮在列表尾部添加一个项目,点击删除则删除列表最后一个项目。AnimatedListState
为我们提供了添加及删除项目的方法:insertItem
、removeItem
,通过这两个方法完成我们的需求。要想获取AnimatedListState
可通过我们定义的_listKey
或者使用AnimatedList.of(context)
,两者区别在于AnimatedList.of(context)
只能在项目内部使用(此处context
为itemBuilder
的context
),而_listKey
在外部也可以获取到AnimatedListState
。注意在操作Item的同时要更新我们的数据。
Positioned(
bottom: 30,
right: 10,
child: FloatingActionButton(
heroTag: 'remove',
onPressed: () {
int data = _data.last;
int index = _data.length - 1;
_data.remove(data);
_listKey.currentState.removeItem(index, (context, animation) => myListItem(context, data.toString(), animation), duration: Duration(seconds: 1));
},
child: Icon(Icons.remove),
),
),
Positioned(
bottom: 30,
right: 70,
child: FloatingActionButton(
heroTag: 'add',
onPressed: () {
int num = Random().nextInt(1000);
_data.add(num);
int index = _data.lastIndexOf(num);
_listKey.currentState.insertItem(index, duration: Duration(seconds: 1));
},
child: Icon(Icons.add),
),
)
下面代码是AnimatedList.of(context)
的示例,将下面代码替换SlideTransition
中的Container
的child
即可:
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Text('$text', style: TextStyle(color: Colors.white),),
IconButton(
icon: Icon(Icons.delete_forever, color: Colors.white,),
onPressed: (){
int index = _data.indexOf(int.parse(text));
_data.removeAt(index);
AnimatedList.of(context).removeItem(index, (context, animation) => myListItem(context, text, animation), duration: Duration(seconds: 1));
},
)
],
),
重新运行项目: