Flutter PageView, могу ли я анимировать удаление элементов из списка?
Я новичок в флаттере и пытаюсь создать анимацию в PageView. если быть точным, я хочу анимировать удаление элемента.
Я пробовал несколько способов оживить его, и, помимо решения, способ, которым вы, ребята, решали бы такую проблему, также был бы полезен для моих навыков флаттера.
Что я пробовал до сих пор:
- Анимация заполнения и непрозрачности
- проблема в том, что когда я устанавливаю отступ в setState в onLongPress, он перестраивает виджет и снова переопределяет заполнение с помощью активного или неактивного CardPadding (я думаю)
- Анимация ширины и высоты
- Я просто не могу заставить работать обе эти ценности
- Анимация viewportFraction в PageViewController
- Не знал бы, как это сделать, и возможно ли это сделать только для определенной "страницы"
Ниже приведен (урезанный) код, который я написал до сих пор.
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 была бы лучше всего, потому что смежные "Pages" тоже движутся навстречу друг другу?
Спасибо!
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
просто глобальный ключ, который обеспечивает доступ к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
может выглядеть так: