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