欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

flutter 实现 有删除动画的 listview

程序员文章站 2022-06-18 18:26:07
个人开发app中,需要开发一个带有删除功能的ListView 效果如下 需求动画分析 列表可以滚动用listView, 有两个动画,第一个动画是透明度变化,第二个是size变化 是顺序执行 实现过程 新建一个动画页面进行单独控制 记得用statefulwidget类,这第二个动画之间涉及到页面刷新切 ......

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

效果如下

flutter 实现 有删除动画的 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简单的改造实现的补位动画,希望留言给我地址,非常感谢