Flutter PageView,我可以动画从列表中删除项目吗?
Posted
技术标签:
【中文标题】Flutter PageView,我可以动画从列表中删除项目吗?【英文标题】:Flutter PageView, can i animate removing items from list? 【发布时间】: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 将是最好的,因为相邻的“页面”也会相互移动?
谢谢!
【问题讨论】:
【参考方案1】:我不确定这是否是您要找的东西,但就是这样。
这样做的一种方法是简单地使用 Flutter 中提供的小部件。其中两个可以帮助您:AnimatedList 和 Dismissible。
现在,你可以这样做:
// 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 应用程序抽屉一样工作,所以水平刷卡,通过捕捉我的意思是动画结束时总是有一张卡正好在中间以上是关于Flutter PageView,我可以动画从列表中删除项目吗?的主要内容,如果未能解决你的问题,请参考以下文章