温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

flutter如何实现带删除动画的listview功能

发布时间:2021-05-22 09:41:11 阅读:348 作者:小新 栏目:开发技术
开发者测试专用服务器限时活动,0元免费领,库存有限,领完即止! 点击查看>>

这篇文章将为大家详细讲解有关flutter如何实现带删除动画的listview功能,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

个人开发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, durationDuration(milliseconds150));
    lucencyAnimation = Tween(begin1.0, end0.0).animate(
        CurvedAnimation(parent: lucencyController, curve: Curves.easeOut));

    sizeController =
        AnimationController(vsync: this, durationDuration(milliseconds250));
    sizeAnimation = Tween(begin1.0, end0.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, durationDuration(milliseconds150));
    lucencyAnimation = Tween(begin1.0, end0.0).animate(
        CurvedAnimation(parent: lucencyController, curve: Curves.easeOut));

    sizeController =
        AnimationController(vsync: this, durationDuration(milliseconds250));
    sizeAnimation = Tween(begin1.0, end0.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,
            childContainer(
              heightduSetWidth(100),
              widthdouble.infinity,
            ),
          )
        : FadeTransition(
            opacity: lucencyAnimation,
            childContainer(
              alignment: Alignment.center,
              padding: EdgeInsets.only(
                leftduSetWidth(15),
                rightduSetWidth(15),
              ),
              heightduSetWidth(100),
              childbuildRow(),
            ),
          );
  }

  Widget buildRow() {
    ///设置显示的样式
    bool _isSub = false;
    Color _isSubColor = Color.fromRGBO(245771301);
    Color _isSubBackColor = Colors.transparent;

    Widget isSubWidget = InkWell(
      childContainer(
        alignment: Alignment.center,
        widthduSetWidth(55),
        heightduSetWidth(28),
        decorationBoxDecoration(
          color: _isSubBackColor,
          border: Border.all(color: _isSubColor),
          borderRadius: BorderRadius.circular(duSetWidth(15)),
        ),
        childText(
          '+ 书架',
          styleTextStyle(
            color: _isSubColor,
          ),
        ),
      ),
      onTap: () {
        if (_isSub)
          print('dasd');
        else
          print('dsada');
      },
    );

    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: [
        Container(
          widthduSetWidth(60),
          heightduSetWidth(80),
          childClipRRect(
            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(
          widthduSetWidth(155),
          heightduSetWidth(80),
          childColumn(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Container(
                heightduSetWidth(25),
                alignment: Alignment.centerLeft,
                widthdouble.infinity,
                childText(
                  '这是标题',
                  maxLines1,
                  overflow: TextOverflow.ellipsis,
                  styleTextStyle(
                    color: Colors.white,
                    fontSizeduSetFontSize(16),
                  ),
                ),
              ),
              Container(
                heightduSetWidth(20),
                alignment: Alignment.centerLeft,
                widthdouble.infinity,
                childText(
                  '这是副标题',
                  maxLines1,
                  overflow: TextOverflow.ellipsis,
                  styleTextStyle(
                    color: Color.fromRGBO(1621681861),
                    fontSizeduSetFontSize(14),
                  ),
                ),
              ),
            ],
          ),
        ),
        Container(
          widthduSetWidth(100),
          heightduSetWidth(80),
          padding: EdgeInsets.only(
            topduSetWidth(4),
          ),
          alignment: Alignment.center,
          childRow(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              isSubWidget,
              InkWell(
                onTap: () async {
                  await lucencyController.forward();
                  setState(() {
                    isChange = true;
                    sizeController.forward();
                  });
                },
                childContainer(
                  alignment: Alignment.center,
                  widthduSetWidth(35),
                  heightduSetWidth(28),
                  decorationBoxDecoration(
                    border: Border.all(
                      color: Color.fromRGBO(1131181401),
                    ),
                    borderRadius: BorderRadius.circular(duSetWidth(15)),
                  ),
                  childIcon(
                    Icons.delete,
                    color: Color.fromRGBO(1131181401),
                    sizeduSetFontSize(16),
                  ),
                ),
              ),
            ],
          ),
        )
      ],
    );
  }
}

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

下列是在页面使用

class HistoryPage extends StatefulWidget {
  @override
  _HistoryPageState createState() => _HistoryPageState();
}

class _HistoryPageState extends State<HistoryPage{
 
 @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBarAppBar(),
      bodyListView(
        children: [
          AnimationListItem(),
          AnimationListItem(),
          AnimationListItem(),
          AnimationListItem(),
        ],
      ),
    );
  }

  /// 构造appbar
  Widget buildAppabr() {
    return AppBar(
      backgroundColor: Color.fromRGBO(3339461),
      brightness: Brightness.dark,
      centerTitletrue,
      titleText(
        '浏览记录',
        styleTextStyle(
          fontSizeduSetFontSize(16),
          color: Colors.white,
        ),
      ),
      leadingIconButton(
        iconIcon(
          Icons.arrow_back_ios,
          color: Colors.white,
          sizeduSetFontSize(18),
        ),
        onPressed: () {
          Get.back();
        },
      ),
    );
  }
}

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

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

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

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

关于“flutter如何实现带删除动画的listview功能”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI

开发者交流群×