我对飘动很陌生,我正在尝试在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动画是最好的,因为相邻的“页面”也朝着彼此移动?
谢谢!
答案 0 :(得分: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)
来简单地“自我调用”的吗?这样便可以对行本身进行动画处理(不存在)。
请务必观看上述文档页面中的视频!他们将有助于理解某些构造。