2

我对颤动很陌生,我正在尝试在 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 将是最好的,因为相邻的“页面”也会相互移动?

谢谢!

4

1 回答 1

2

我不确定这是否是您正在寻找的东西,但这里有。

一种方法是简单地使用 Flutter 中提供的 Widget。其中两个将帮助您: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只是一个提供对 的访问的全局键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可能的样子: SizeTransition 移除

于 2019-11-20T22:10:05.987 回答