我对飘动很陌生,我正在尝试在PageView上做一些动画。确切地说,我想为删除一个项目设置动画。
我已经尝试了无数种方法对其进行动画处理,除了提供解决方案之外,你们如何解决此类问题的方法也将有助于我的工作。
到目前为止我尝试过的:
下面是我到目前为止编写的(分解后的)代码。
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中提供的小部件。其中两个将帮助您: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)
来“自我调用”吗?这样就可以对行本身进行动画处理(不存在)。
请务必观看上述文档页面中的视频!他们将帮助理解某些构造。