Flutter предоставляет огромное количество замечательных сторонних пакетов для создания анимационных эффектов в приложениях, однако существуют также встроенные методы для создания более тонких анимационных эффектов вручную.
Требования
Для работы с cross-screen анимацией нужно знать, как создавать маршруты. Вы можете просмотреть документацию, если пока что вы еще не знакомы с основами создания маршрутов.
Линейная анимация
Основные три части анимации – это ticker для управления временем, controller для регистрации параметров (таких как продолжительность), а также значения, которые мы хотим изменить. Прежде чем наш виджет будет отрисован, мы можем установить в initState параметры для контроллера, определить его направление и добавить прослушивателя для сброса состояния виджетов при каждом изменении.
По умолчанию контроллер переместит изменение с 0 на 1 за то время, которое мы установим в параметре duration; мы можем отобразить controller.value в прослушивателе, чтобы увидеть, как это работает. Установив свойства upperBound или lowerBound, мы можем изменить наши начальные и конечные значения по умолчанию.
Откройте файл main.dart:
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
AnimationController controller;
void initState() {
super.initState();
controller = AnimationController(
duration: Duration(seconds: 1),
vsync: this); // Links this controller to this widget so it won't run if the parent widget isn't rendered, to save on resources.
controller.forward();
controller.addListener(() => setState(() {}));
}
}
Чтобы использовать анимацию, нам просто нужно установить все, что мы хотим, например непрозрачность, в controller.value.
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Opacity(
opacity: controller.value,
child: Container(width: 50, height: 50, color: Colors.red),
),
),
);
}
Кривая анимация
Вместо скучной линейной анимации можно использовать различные виды кривой анимации, что позволяет точно контролировать, как изменяется контроллер. Для этого мы можем с помощью CurvedAnimation создать своего рода оболочку над исходным контроллером. Эта оболочка примет наш контроллер в качестве родительского и кривую, которую нужно применить. При использовании такой анимации не может быть нижней и верхней границ вне 0 и 1. В документации есть действительно широкий список опций по работе с этим видом.
Еще один полезный метод для контроллера – addStatusListener, который позволяет задействовать его жизненный цикл. При этом контроллер запускает завершенное или отклоненное событие всякий раз, когда его значение достигает своей верхней или нижней границы. Мы можем использовать этот метод с его методами forward и reverse, чтобы создать бесконечный цикл анимации.
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
AnimationController controller;
Animation animation;
void initState() {
super.initState();
controller = AnimationController(
duration: Duration(seconds: 1),
vsync: this);
animation = CurvedAnimation(parent: controller, curve: Curves.slowMiddle);
controller.forward();
animation.addListener(() => setState(() {}));
controller.addStatusListener((status) {
if (status == AnimationStatus.completed) controller.reverse(from: 400);
else if (status == AnimationStatus.dismissed) controller.forward();
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
margin: EdgeInsets.only(bottom: animation.value * 400),
width: 50,
height: 50,
color: Colors.red),
),
);
}
}
Анимация tween
Мы можем работать с диапазонами других составляющих, таких как цвета, с помощью анимации tween (сокращение от between, «промежуточный»). Как и в случае с предыдущим методом анимации, этот метод действует как оболочка для контроллера или анимации, где мы можем установить значение для цвета.
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
AnimationController controller;
Animation animation;
Animation changeColor;
void initState() {
super.initState();
controller =
AnimationController(duration: Duration(seconds: 1), vsync: this);
animation = CurvedAnimation(parent: controller, curve: Curves.slowMiddle);
changeColor = ColorTween(begin: Colors.red, end: Colors.blue).animate(animation);
controller.forward();
animation.addListener(() => setState(() {}));
controller.addStatusListener((status) {
if (status == AnimationStatus.completed) controller.reverse(from: 400);
else if (status == AnimationStatus.dismissed) controller.forward();
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
margin: EdgeInsets.only(bottom: animation.value * 400),
width: 50,
height: 50,
color: changeColor.value),
),
);
}
}
Cross-screen анимация
Еще одна замечательная техника анимации – виджет Hero, который обеспечивает переход между виджетами на разных экранах. Нужно просто обернуть каждый отдельный виджет Hero с помощью соответствующих тегов. Теги должны быть уникальными, и на экране их не может быть больше одного. Вот, например, первый экран:
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
SizedBox(height: 1),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Hero(tag: 'icon', child: Icon(Icons.add)),
]),
Navbar()
]));
}
И второй:
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
SizedBox(height: 1),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
SizedBox(width: 1),
Hero(
tag: 'icon',
child: Icon(Icons.add, color: Colors.red, size: 75)),
]),
Navbar()
]),
);
}
Заключение
На самом деле мы только прикоснулись к тому, на что способен Flutter в плане анимации. Большинство веб-технологий прошлого оставляли анимацию на потом, но команда разработчиков Flutter проделала потрясающую работу – теперь можно держать анимацию в уме при разработке своих приложений.
Читайте также: Как создать свое первое приложение Flutter
