flutter 实现 有删除动画的 listview

个人开发app中,需要开发一个带有删除功能的ListView

效果如下

 

 

需求动画分析

 

列表可以滚动用listView,

有两个动画,第一个动画是透明度变化,第二个是size变化

是顺序执行

 

实现过程

新建一个动画页面进行单独控制

记得用statefulwidget类,这第二个动画之间涉及到页面刷新切换widget

记得with tickerproviderstatemixin 这个是动画类状态管理的必备

class AnimationListItem extends StatefulWidget { AnimationListItem(); @override _AnimationListItemState createState() => _AnimationListItemState();}class _AnimationListItemState extends State<AnimationListItem> with TickerProviderStateMixin { @override Widget build(BuildContext context) { // TODO: implement build return Container(); }}

 

动画流程

声明

//控制器  AnimationController lucencyController; AnimationController sizeController;// 动画 Animation<double> lucencyAnimation; Animation<double> sizeAnimation;

 

初始化

///必须在initstate这个生命周期进行初始化 @override void initState() { // TODO: implement initState super.initState(); lucencyController =  AnimationController(vsync: this, duration: Duration(milliseconds: 150)); lucencyAnimation = Tween(begin: 1.0, end: 0.0).animate(  CurvedAnimation(parent: lucencyController, curve: Curves.easeOut)); sizeController =  AnimationController(vsync: this, duration: Duration(milliseconds: 250)); sizeAnimation = Tween(begin: 1.0, end: 0.0).animate(  CurvedAnimation(parent: sizeController, curve: Curves.easeOut)); }

 

注销 

@override void dispose() { lucencyController.dispose(); sizeController.dispose(); super.dispose(); }

 

最后内容呈现

class AnimationListItem extends StatefulWidget { AnimationListItem(); @override _AnimationListItemState createState() => _AnimationListItemState();}class _AnimationListItemState extends State<AnimationListItem> with TickerProviderStateMixin { AnimationController lucencyController; AnimationController sizeController; Animation<double> lucencyAnimation; Animation<double> sizeAnimation; bool isChange = false; @override void initState() { // TODO: implement initState super.initState(); lucencyController =  AnimationController(vsync: this, duration: Duration(milliseconds: 150)); lucencyAnimation = Tween(begin: 1.0, end: 0.0).animate(  CurvedAnimation(parent: lucencyController, curve: Curves.easeOut)); sizeController =  AnimationController(vsync: this, duration: Duration(milliseconds: 250)); sizeAnimation = Tween(begin: 1.0, end: 0.0).animate(  CurvedAnimation(parent: sizeController, curve: Curves.easeOut)); } @override Widget build(BuildContext context) { return buildItemBox(); } @override void dispose() { lucencyController.dispose(); sizeController.dispose(); super.dispose(); } Widget buildItemBox() { return isChange  ? SizeTransition(   axis: Axis.vertical,   sizeFactor: sizeAnimation,   child: Container(    height: duSetWidth(100),    width: double.infinity,   ),   )  : FadeTransition(   opacity: lucencyAnimation,   child: Container(    alignment: Alignment.center,    padding: EdgeInsets.only(    left: duSetWidth(15),    right: duSetWidth(15),    ),    height: duSetWidth(100),    child: buildRow(),   ),   ); } Widget buildRow() { ///设置显示的样式 bool _isSub = false; Color _isSubColor = Color.fromRGBO(245, 77, 130, 1); Color _isSubBackColor = Colors.transparent; Widget isSubWidget = InkWell(  child: Container(  alignment: Alignment.center,  width: duSetWidth(55),  height: duSetWidth(28),  decoration: BoxDecoration(   color: _isSubBackColor,   border: Border.all(color: _isSubColor),   borderRadius: BorderRadius.circular(duSetWidth(15)),  ),  child: Text(   '+ 书架',   style: TextStyle(   color: _isSubColor,   ),  ),  ),  onTap: () {  if (_isSub)   print('dasd');  else   print('dsada');  }, ); return Row(  mainAxisAlignment: MainAxisAlignment.spaceBetween,  children: [  Container(   width: duSetWidth(60),   height: duSetWidth(80),   child: ClipRRect(   borderRadius: BorderRadius.circular(duSetWidth(5)),   child: Image.network(    'https://gimg2.baidu.com/image_search/src=http%3A%2F%2F00.minipic.eastday.com%2F20170307%2F20170307164725_114ea3c04f605e59bd10699f37870267_13.jpeg&refer=http%3A%2F%2F00.minipic.eastday.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1623596389&t=946dba98698d8d67d773ea8f7af55f45',    fit: BoxFit.cover,   ),   ),  ),  Container(   width: duSetWidth(155),   height: duSetWidth(80),   child: Column(   mainAxisAlignment: MainAxisAlignment.center,   children: [    Container(    height: duSetWidth(25),    alignment: Alignment.centerLeft,    width: double.infinity,    child: Text(     '这是标题',     maxLines: 1,     overflow: TextOverflow.ellipsis,     style: TextStyle(     color: Colors.white,     fontSize: duSetFontSize(16),     ),    ),    ),    Container(    height: duSetWidth(20),    alignment: Alignment.centerLeft,    width: double.infinity,    child: Text(     '这是副标题',     maxLines: 1,     overflow: TextOverflow.ellipsis,     style: TextStyle(     color: Color.fromRGBO(162, 168, 186, 1),     fontSize: duSetFontSize(14),     ),    ),    ),   ],   ),  ),  Container(   width: duSetWidth(100),   height: duSetWidth(80),   padding: EdgeInsets.only(   top: duSetWidth(4),   ),   alignment: Alignment.center,   child: Row(   mainAxisAlignment: MainAxisAlignment.spaceBetween,   children: [    isSubWidget,    InkWell(    onTap: () async {     await lucencyController.forward();     setState(() {     isChange = true;     sizeController.forward();     });    },    child: Container(     alignment: Alignment.center,     width: duSetWidth(35),     height: duSetWidth(28),     decoration: BoxDecoration(     border: Border.all(      color: Color.fromRGBO(113, 118, 140, 1),     ),     borderRadius: BorderRadius.circular(duSetWidth(15)),     ),     child: Icon(     Icons.delete,     color: Color.fromRGBO(113, 118, 140, 1),     size: duSetFontSize(16),     ),    ),    ),   ],   ),  )  ], ); }}

 

dusetwidth是我自定义的函数可以不用管,自己替换

 

下列是在页面使用

class HistoryPage extends StatefulWidget { @override _HistoryPageState createState() => _HistoryPageState();}class _HistoryPageState extends State<HistoryPage> {  @override Widget build(BuildContext context) { return Scaffold(  appBar: AppBar(),  body: ListView(  children: [   AnimationListItem(),   AnimationListItem(),   AnimationListItem(),   AnimationListItem(),  ],  ), ); } /// 构造appbar Widget buildAppabr() { return AppBar(  backgroundColor: Color.fromRGBO(33, 39, 46, 1),  brightness: Brightness.dark,  centerTitle: true,  title: Text(  '浏览记录',  style: TextStyle(   fontSize: duSetFontSize(16),   color: Colors.white,  ),  ),  leading: IconButton(  icon: Icon(   Icons.arrow_back_ios,   color: Colors.white,   size: duSetFontSize(18),  ),  onPressed: () {   Get.back();  },  ), ); }}

 

这个我原来是准备使用animatedList来进行实现的,最后发现,animatedList里面只能设置移除动画,不能实现补位动画

第一个透明度的动画就是移除动画,第二个size变化就是补位动画,

animatedList没有补位,所以下方list直接移动上去会显得非常突兀,我看了看源码,修改较为麻烦。所以就直接用动画变换来写

这个List内的内容,并不是直接移除,而是替换成高低为0 的一个盒子

如果有animatedList简单的改造实现的补位动画,希望留言给我地址,非常感谢









原文转载:http://www.shaoqun.com/a/744776.html

跨境电商:https://www.ikjzd.com/

派代:https://www.ikjzd.com/w/2197

blibli:https://www.ikjzd.com/w/1676


个人开发app中,需要开发一个带有删除功能的ListView效果如下需求动画分析列表可以滚动用listView,有两个动画,第一个动画是透明度变化,第二个是size变化是顺序执行实现过程新建一个动画页面进行单独控制记得用statefulwidget类,这第二个动画之间涉及到页面刷新切换widget记得withtickerproviderstatemixin这个是动画类状态管理的必备classAni
巨鲸:https://www.ikjzd.com/w/1986
马莎:https://www.ikjzd.com/w/2385
海豚村:https://www.ikjzd.com/w/1779
疫情隔离解封后美国人怎么样了?2020年美国出了什么大事?:https://www.ikjzd.com/home/120316
老公搂着我做春梦把我吓醒:http://lady.shaoqun.com/a/270708.html
亚马逊旺季过后,跨境电商卖家清库存的7大招!:https://www.ikjzd.com/home/15616

Post a Comment