flutter 实现 有删除动画的 listview
程序员文章站
2022-03-04 09:56:50
个人开发app中,需要开发一个带有删除功能的ListView 效果如下 需求动画分析 列表可以滚动用listView, 有两个动画,第一个动画是透明度变化,第二个是size变化 是顺序执行 实现过程 新建一个动画页面进行单独控制 记得用statefulwidget类,这第二个动画之间涉及到页面刷新切 ......
个人开发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简单的改造实现的补位动画,希望留言给我地址,非常感谢
推荐阅读
-
Android使用ListView实现滚轮的动画效果实例
-
纯css3无js实现的Android Logo(有简单动画)
-
利用Flutter实现“孔雀开屏”的动画效果
-
用PPT制作有动画声音的国庆电子报刊实现升国旗唱国歌效果
-
android使用flutter的ListView实现滚动列表的示例代码
-
flutter实现带删除动画的listview功能
-
flutter 实现 有删除动画的 listview
-
不用框架,纯PHP,能实现这样的功能吗?有很多页面,有插入删除修改功能,只写一种增删改方法,其他页面也能共用这一个方法
-
不要框架,纯PHP,能实现这样的功能吗?有很多页面,有插入删除修改功能,只写一种增删改方法,其他页面也能共用这一个方法
-
Android使用ListView实现滚轮的动画效果实例