Прикольные анимации для Flutter-приложений


Я покажу вам 6 прикольных анимационных эффектов, которые можно попробовать в своих приложениях. Добавлять анимацию с Flutter — одно удовольствие. И делать это можно по-разному. Например, можно скачать пакет с dart pub или воспользоваться виджетом AnimatedBuilder, который позволяет настроить каждую деталь анимации.

В этой статье я буду работать с виджетом AnimatedBuilder. Если вы не знакомы с ним, то почитайте документацию. Раз мы решили поработать с AnimatedBuilder, то нам потребуются два дополнительных виджета:

1. AnimationController — задает длительность анимации;

2. Animation — определяет тип и стиль анимации.

Проще говоря, эти виджеты используются для настройки и обработки анимации. Не забудьте протестировать анимацию в виджете изменяемых состояний StatefulWidget. А в определение класса обязательно добавьте SingleTickerProviderStateMixin. Он нужен для управления временем в анимации.

Готовы начать? Поехали.

Базовый макет

Я создал базовый макет, на котором вы можете потренироваться в настройке и переключении анимации. Выглядит он вот так:

Базовый макет

В процессе работы мы будем пользоваться разными изображениями. Вы можете добавить свои изображения или другие виджеты.

Триггером для анимации у нас служит плавающая кнопка снизу. Я буду активировать анимацию через вызов _controller.forward().

Не пугайтесь кода ниже. Пользуйтесь им для настройки контроллера и виджета анимации. 

Теперь я познакомлю вас с разными типами анимации в двух блоках кода — для определения и использования анимации. Все очень просто: сначала выбираете понравившийся тип анимации, а затем копируете и вставляете два блока кода. Первый нужен для запуска контроллера, а второй — для работы с анимацией.

import 'package:flutter/material.dart'; class MyHomePage extends StatefulWidget { @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin{ //*-----определяем Animation и AnimationController-----* AnimationController _controller; Animation _myAnimation; //*-----запускаем Animation и AnimationController-----* @override void initState() { super.initState(); } @override void dispose() { super.dispose(); //-disposing the animation controller- _controller.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Flutter Animations"), ), body: Center( child: Container( width: 250, height: 250, decoration: BoxDecoration( image: new DecorationImage( image: new AssetImage( 'assets/images/sample-image.png', ) ) ), ) ), floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat, floatingActionButton: FloatingActionButton( child: Icon(Icons.play_arrow), onPressed: (){ //*------включаем анимацию-----* _controller.forward(); }, ), ); } }

01. Появление/исчезновение

Fade-эффект

Воспользуйтесь кодом ниже для определения анимации. Лучше всего это делать через метод initState. Теперь он будет запускаться только при отображении StatefulWidget.

AnimationController _controller; Animation _myAnimation; void initState() { // TODO: implement initState super.initState(); _controller = AnimationController( vsync: this, duration: Duration(milliseconds: 1200), ); _myAnimation = CurvedAnimation(parent: _controller, curve: Curves.easeIn); }

Во Flutter уже есть встроенный виджет под названием FadeTransition. Таким образом, мы можем обернуть наш виджет-контейнер в FadeTransition, а затем настроить динамические значения для непрозрачности.

body: Center( child: FadeTransition( opacity: _myAnimation, child: Container( width: 100, height: 100, decoration: BoxDecoration( image: new DecorationImage( image: new AssetImage( 'assets/images/ghost.png', ) ) ), ), ) ),

02. Изменение размера/пульсация

Это тоже простая разновидность анимации. Для начала, зададим нужные параметры.

AnimationController _controller; Animation<Size> _myAnimation; @override void initState() { // TODO: implement initState super.initState(); _controller = AnimationController( vsync: this, duration: Duration(milliseconds: 1000), ); _myAnimation = Tween<Size>( begin: Size(100, 100), end: Size(120, 120) ).animate( CurvedAnimation(parent: _controller, curve: Curves.bounceIn) ); _controller.addStatusListener((AnimationStatus status) { if (status == AnimationStatus.completed) { _controller.repeat(); } }); }

Возможно, сейчас вы заметите что-то новое. Например, мы используем _controller.addStatusListener() каждый раз, когда хотим повторить анимацию. После определения анимации в AnimationController она готова к использованию в виджете-контейнере.

body: Center( child: AnimatedBuilder(animation: _myAnimation, builder: (ctx, ch) => Container( width: _myAnimation.value.width, height: _myAnimation.value.height, decoration: BoxDecoration( image: new DecorationImage( image: new AssetImage( 'assets/images/heart.png', ) ) ), ) ) ),

03. Скольжение

Slide-анимация — это еще одна встроенная функция Flutter. Вот, как ее можно определить.

AnimationController _controller; Animation<Offset> _myAnimation; @override void initState() { // TODO: implement initState super.initState(); _controller = AnimationController( duration: const Duration(seconds: 2), vsync: this, ); _myAnimation = Tween<Offset>( begin: Offset.zero, end: const Offset(1.5, 0.0), ).animate(CurvedAnimation( parent: _controller, curve: Curves.elasticIn, )); }

Чтобы воспользоваться анимацией, оберните ее в виджет SlideTransition. Проще простого, не так ли?

body: Center( child: SlideTransition( position: _myAnimation, child: const Padding( padding: EdgeInsets.all(8.0), child: FlutterLogo(size: 150.0), ), ), ),

04. Прыгающая анимация

Еще одна забавная разновидность, которую можно попробовать. Во многом она похожа на анимацию пульсации. Только помните, что в этот раз нам нужно будет изменить отступы контейнера. Давайте определим параметры.

AnimationController _controller; Animation<double> _slideAnimation; @override void initState() { // TODO: implement initState super.initState(); _controller = AnimationController( vsync: this, duration: Duration(milliseconds: 1000), ); _slideAnimation = Tween(begin: 200.0, end: 120.0).animate( CurvedAnimation( parent: _controller, curve: Interval(0.0, 1.0, curve: Curves.elasticIn), ), )..addStatusListener((AnimationStatus status) { if (status == AnimationStatus.completed) { _controller.repeat(reverse: true); } }); }

Будьте осторожны — мы играем с огнем. Если я выставлю граничное значение 0.0, то появится ошибка. Для тех, кто уже работал с Flutter, это совсем не новость. Да, перед вами — ошибка переполнения, она же — overflow error. Мы не можем быть уверенными в том, что значения в этих границах будут меняться. Особенно в случае, если эффект анимации (эластичный) выйдет за пределы границ. Запомните, что отступы не могут иметь отрицательного значения. 

Теперь, когда мы настроили все необходимые параметры, самое время воспользоваться анимацией.

body: AnimatedBuilder(animation: _slideAnimation, builder: (ctx, ch) => Container( width: 100, height: 100, margin: EdgeInsets.only( top: _slideAnimation.value, left: 125 ), decoration: BoxDecoration( image: new DecorationImage( image: new AssetImage( 'assets/images/bounce-ball.png', ) ) ), ) ),

05. 3D-переворот

Flip-анимация — это простой и прикольный эффект, который легко добавить в приложение. (Одна из моих любимых анимаций). Давайте посмотрим, как все реализовать.

AnimationController _controller; Animation _myAnimation; AnimationStatus _animationStatus = AnimationStatus.dismissed; @override void initState() { super.initState(); _controller = AnimationController(vsync: this, duration: Duration(seconds: 1)); _myAnimation = Tween(end: 1.0, begin: 0.0).animate(_controller) ..addListener(() { setState(() {}); }) ..addStatusListener((status) { _animationStatus = status; }); }

Здесь появляется кое-что новенькое — AnimationStatus. Им я пользовался для реализации прямых и обратных функций. Этот дополнительный виджет помогает мне получить текущий статус анимации.

Тут я воспользовался простым контейнером, чтобы показать flip-анимацию в действии.

body: Center( child: Transform( alignment: FractionalOffset.center, transform: Matrix4.identity() ..setEntry(3, 2, 0.002) ..rotateX(pi*(_myAnimation.value)), child: Container( color: Colors.blueAccent, width: 200, height: 200, child: Icon( Icons.accessibility_new, color: Colors.white, size: 50, ), ), ) ),

06. Вращение с падением

Перейдем к более сложным примерам. Здесь я объединил сразу несколько эффектов. Мы называем это последовательностью анимации. Посмотрите, как можно определить анимацию врещения.

AnimationController _controller; Animation _rotateAnimation; Animation<double> _slideAnimation; Animation<double> _opacityAnimation; @override void initState() { // TODO: implement initState super.initState(); _controller = AnimationController( vsync: this, duration: Duration(milliseconds: 3000), ); _rotateAnimation = Tween(end: 0.15, begin: 0.0) .animate( CurvedAnimation( parent: _controller, curve: Interval(0.0, 0.5, curve: Curves.bounceInOut), ), ); _slideAnimation = Tween(begin: 100.0, end: 600.0).animate( CurvedAnimation( parent: _controller, curve: Interval(0.5, 1.0, curve: Curves.fastOutSlowIn), ), ); _opacityAnimation = Tween(begin: 1.0, end: 0.0).animate( CurvedAnimation( parent: _controller, curve: Interval(0.5, 1.0, curve: Curves.fastOutSlowIn), ), ); }

Обратите внимание, что при определении анимации мы пользуемся 3 отдельными виджетами Animation. И для всех них берется один AnimationController. А еще я передавал разные значения для каждого виджета Interval. Именно так и задается последовательность анимации.

Теперь давайте посмотрим, как работает последовательность анимации:

body: AnimatedBuilder( animation: _slideAnimation, builder: (ctx, ch) => Container( width: 200, height: 100, padding: EdgeInsets.all(0), margin: EdgeInsets.only( left: 75, top: _slideAnimation.value, ), child: RotationTransition( turns: _rotateAnimation, child: Center( child: Text('Animation', style: TextStyle( fontSize: 40, fontWeight: FontWeight.bold, color: Color.fromRGBO(0, 0, 128, _opacityAnimation.value) ),), ), ), ), ),

Все правильно! Нам нужен еще один виджет –AnimatedBuilder. Затем мы можем поменять значения контейнера. В этом примере я изменял отступы (для смены положения объекта) и непрозрачность.

Примеры анимации можно посмотреть на Github


Перевод статьи Sahan Amarsha: Cool Flutter Animations That You Can Try


Поделиться статьей:


Вернуться к статьям

Комментарии

    Ничего не найдено.