溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

flutter如何實現(xiàn)帶刪除動畫的listview功能

發(fā)布時間:2021-05-22 09:41:11 來源:億速云 閱讀:342 作者:小新 欄目:開發(fā)技術(shù)

這篇文章將為大家詳細講解有關(guān)flutter如何實現(xiàn)帶刪除動畫的listview功能,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

個人開發(fā)app中,需要開發(fā)一個帶有刪除功能的ListView

效果如下

flutter如何實現(xiàn)帶刪除動畫的listview功能

需求動畫分析

列表可以滾動用listView,

有兩個動畫,第一個動畫是透明度變化,第二個是size變化

是順序執(zhí)行

實現(xiàn)過程

新建一個動畫頁面進行單獨控制

記得用statefulwidget類,這第二個動畫之間涉及到頁面刷新切換widget

記得with tickerproviderstatemixin 這個是動畫類狀態(tài)管理的必備

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();
  }

最后內(nèi)容呈現(xiàn)

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() {
    ///設(shè)置顯示的樣式
    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是我自定義的函數(shù)可以不用管,自己替換

下列是在頁面使用

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(),
        ],
      ),
    );
  }

  /// 構(gòu)造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來進行實現(xiàn)的,最后發(fā)現(xiàn),animatedList里面只能設(shè)置移除動畫,不能實現(xiàn)補位動畫

第一個透明度的動畫就是移除動畫,第二個size變化就是補位動畫,

animatedList沒有補位,所以下方list直接移動上去會顯得非常突兀,我看了看源碼,修改較為麻煩。所以就直接用動畫變換來寫

這個List內(nèi)的內(nèi)容,并不是直接移除,而是替換成高低為0 的一個盒子

關(guān)于“flutter如何實現(xiàn)帶刪除動畫的listview功能”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,使各位可以學(xué)到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI