【问题标题】:Flutter PageView, can i animate removing items from list?Flutter PageView,我可以动画从列表中删除项目吗?
【发布时间】:2020-03-16 15:01:08
【问题描述】:

我是 Flutter 的新手,我正在尝试在 PageView 上做一些动画。准确地说,我想动画删除一个项目。

我尝试了多种方法来制作动画,除了解决方案之外,你们解决此类问题的方式也将有助于我的颤振技巧。

到目前为止我已经尝试过:

  • 动画填充和不透明度
    • 问题在于,当我在 onLongPress 中的 setState 中设置填充时,它会重建小部件并使用活动或非活动 CardPadding 再次覆盖填充(我认为)
  • 动画宽度和高度
    • 我似乎无法让这两个值都起作用
  • 在 PageViewController 上为 viewportFraction 设置动画
    • 不知道该怎么做,是否可以仅针对特定的“页面”执行此操作

下面是我迄今为止编写的(精简的)代码。

class Main extends StatefulWidget {
  @override
  _MainState createState() => _MainState();
}

class _MainState extends State<Main> {
  int activeCard = 0;

  EdgeInsets inActiveCardPadding = EdgeInsets.symmetric(vertical: 120.0, horizontal: 20.0);
  EdgeInsets activeCardPadding = EdgeInsets.symmetric(vertical: 105.0, horizontal: 10.0);

  PageController pageController = PageController(
    initialPage: 0,
    viewportFraction: 0.8,
  );

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      body: SafeArea(
        child: Stack(
          children: <Widget>[
            PageView.builder(
              itemCount: PlantCareApp.plants.length,
              controller: pageController,
              onPageChanged: (activeCardIndex) {
                setState(() {
                  this.activeCard = activeCardIndex;
                });
              },
              itemBuilder: (context, cardIndex) {
                return AnimatedContainer(
                  padding: (activeCard == cardIndex) ? activeCardPadding : inActiveCardPadding;,
                  duration: Duration(milliseconds: 250),
                  child: PlantCard(
                    PlantCareApp.plants[cardIndex],
                    onTap: () {
                      Navigator.pushNamed(context, PlantDetailScreen.route, arguments: PlantCareApp.plants[cardIndex]);
                    },
                    onLongPress: () {
                      setState(() {
                        //
                        // ANIMATE OR TRIGGER ANIMATION HERE
                        //

                        // do the actual removing
                        /*
                          PlantCareApp.plants[cardIndex].remove(); // remove from db
                          PlantCareApp.plants.removeAt(cardIndex); // remove from List
                        */
                      });
                      //PlantCareApp.plants[cardIndex].remove();
                    },
                  ),
                );
              },
            ),
          ],
        ),
      ),
    );
  }
}

任何帮助将不胜感激!你们将如何解决这样的问题,或者您将如何解决这个特定的用例。

我想实际上动画 viewportFraction 将是最好的,因为相邻的“页面”也会相互移动?

谢谢!

【问题讨论】:

    标签: flutter flutter-animation flutter-pageview


    【解决方案1】:

    我不确定这是否是您要找的东西,但就是这样。

    这样做的一种方法是简单地使用 Flutter 中提供的小部件。其中两个可以帮助您:AnimatedListDismissible

    现在,你可以这样做:

    // define somewhere
    final _animatedListGK = GlobalKey<AnimatedListState>();
    
    // put in a function somewhere
    return AnimatedList(
      key: _animatedListGK,
      padding: const EdgeInsets.all(0),
      initialItemCount: PlantCareApp.plants.length,
      itemBuilder: (context, index, animation) {
        return FadeTransition(
          opacity: animation,
          child: _buildDismissibleRow(context, index, PlantCareApp.plants[index])
        );
      }
    );
    

    注意:你不必使用_animatedListGK 全局键本身,这取决于你是否可以使用AnimatedList.of(context)。虽然这是更简单的方法。

    _animatedListGK 只是一个Global Key,它提供对AnimatedList 的访问,因此您可以使用动画执行插入/删除。

    您的可关闭行可能类似于:

    Widget _buildDismissibleRow(BuildContext context, int index, PlantModel plantModel) {
        return Dismissible(
          key: ValueKey<String>(plantModel.someKey),
          direction: DismissDirection.startToEnd,
          background: Container(color: Colors.red),
          onDismissed: (direction) {
            // You could use:
            // AnimatedList.of(context)
            _animatedListGK.currentState.removeItem(
              index,
              (context, animation) => Container(),
              duration: Duration.zero
            );
          },
          child: _buildContent(context, index, plantModel)
        );
    }
    

    您也可以在没有可关闭行的情况下执行此操作,甚至可以在可关闭行的子行中执行此操作(例如_buildContent())。类似于:

    // You could use:
    // AnimatedList.of(context)
    _animatedListGK.currentState.removeItem(
      index,
      (context, animation) {
        return FadeTransition(
          opacity: CurvedAnimation(parent: animation, curve: Interval(0.5, 1.0)),
          child: SizeTransition(
            sizeFactor: CurvedAnimation(parent: animation, curve: Interval(0.0, 1.0)),
            child: _builContent(context, index, plantModel)
          )
        );
      },
      duration: const Duration(milliseconds: 300)
    );
    

    注意SizeTransition 是如何通过调用_builContent(context, index, plantModel) 简单地“调用自身”的?这就是您可以为行本身设置动画的方式(不存在)。

    请务必观看上述文档页面中的视频!它们将有助于理解某些结构。

    可解雇的外观预览:

    SizedTransition 的外观预览:

    【讨论】:

    • 嗨!谢谢你的回答,我一定会试一试的。您能否告诉我 Animatedlist 是否可以水平对齐以及是否可以对齐?
    • @GijsBeijer 我不知道。捕捉到底是什么意思?
    • @voracios 好吧,我正在尝试创建的东西应该像 Android 应用程序抽屉一样工作,所以水平刷卡,通过捕捉我的意思是动画结束时总是有一张卡正好在中间
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-25
    • 2019-10-30
    • 2014-11-21
    • 2021-02-04
    • 1970-01-01
    • 2023-02-25
    相关资源
    最近更新 更多