Ответ
Flutter предоставляет мощную и гибкую систему анимаций, которая делится на два основных типа: неявные (implicit) и явные (explicit). Все анимации работают на 60/120 FPS благодаря движку Skia.
1. Неявные анимации (Implicit Animations)
Самый простой способ. Используются специальные виджеты (с префиксом Animated...), которые автоматически анимируют изменения своих свойств.
bool _selected = false;
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => setState(() => _selected = !_selected),
child: AnimatedContainer(
duration: Duration(milliseconds: 300),
curve: Curves.easeInOut, // Кривая для естественного движения.
width: _selected ? 200 : 100,
height: _selected ? 200 : 100,
color: _selected ? Colors.blue : Colors.grey,
child: Center(child: Text('Tap me')),
),
);
}
Другие примеры: AnimatedOpacity, AnimatedPadding, AnimatedAlign.
2. Явные анимации (Explicit Animations)
Дают полный контроль над анимацией через AnimationController. Используются для сложных, составных или повторяющихся анимаций.
class _RotationAnimation extends StatefulWidget {
@override
_RotationAnimationState createState() => _RotationAnimationState();
}
class _RotationAnimationState extends State<_RotationAnimation>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _animation;
@override
void initState() {
super.initState();
// Контроллер управляет временем анимации (vsync синхронизирует с частотой кадров).
_controller = AnimationController(
vsync: this,
duration: Duration(seconds: 2),
);
// Tween определяет диапазон значений анимации.
_animation = Tween<double>(begin: 0, end: 2 * pi).animate(_controller);
_controller.repeat(); // Запускаем анимацию на повтор.
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _animation,
builder: (context, child) {
return Transform.rotate(
angle: _animation.value,
child: FlutterLogo(size: 100),
);
},
);
}
@override
void dispose() {
_controller.dispose(); // Важно: всегда освобождаем контроллер.
super.dispose();
}
}
3. Анимации на основе физики (Physics-based)
Имитируют реальное движение (пружины, гравитация) через SpringSimulation, GravitySimulation.
4. Hero-анимации
Для плавного перехода виджета между экранами (навигации).
// На первом экране
Hero(
tag: 'avatar', // Уникальный тег.
child: CircleAvatar(backgroundImage: NetworkImage(url)),
)
// На втором экране используем виджет с тем же тегом.
Hero(
tag: 'avatar',
child: Image.network(url, fit: BoxFit.cover),
)
5. Интеграция с Rive/Lottie
Для сложных векторных анимаций, созданных дизайнерами, используется пакет rive или lottie. Это позволяет загружать готовые анимации из Figma или After Effects.
Ключевой принцип: В Flutter анимация — это просто интерполяция значений (числа, цвета и т.д.) во времени, управляемая Animation объектами. Виджеты перерисовываются на каждом кадре с новым значением, создавая иллюзию движения.
Ответ 18+ 🔞
Да ты посмотри, какая у них тут система анимаций развесистая! Flutter, сука, подходит к делу с размахом — тут тебе не просто моргнуть кнопкой, тут целый ёперный театр можно развернуть. Всё делится на два главных лагеря, и оба работают на движке Skia, так что плавность — просто овердохуища, 60 или даже 120 кадров в секунду.
1. Неявные анимации (Implicit Animations)
Это для ленивых, в хорошем смысле слова. Самый простой способ, не надо париться с контроллерами. Берёшь специальные виджеты, у которых в названии Animated... и меняешь у них свойства. Они сами, ебушки-воробушки, всё плавненько перетекают.
bool _selected = false;
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => setState(() => _selected = !_selected),
child: AnimatedContainer(
duration: Duration(milliseconds: 300),
curve: Curves.easeInOut, // Кривая для естественного движения.
width: _selected ? 200 : 100,
height: _selected ? 200 : 100,
color: _selected ? Colors.blue : Colors.grey,
child: Center(child: Text('Tap me')),
),
);
}
Есть ещё куча таких виджетов: AnimatedOpacity, AnimatedPadding — в общем, на любой вкус. Поставил — и волнение ебать, как красиво всё меняется.
2. Явные анимации (Explicit Animations)
А вот это уже для крутых пацанов, которые хотят полный контроль. Тут тебе и AnimationController, и кривые, и повторения — полный картель. Используешь, когда нужно что-то сложное, вроде бесконечного вращения или целой последовательности действий.
class _RotationAnimation extends StatefulWidget {
@override
_RotationAnimationState createState() => _RotationAnimationState();
}
class _RotationAnimationState extends State<_RotationAnimation>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _animation;
@override
void initState() {
super.initState();
// Контроллер управляет временем анимации (vsync синхронизирует с частотой кадров).
_controller = AnimationController(
vsync: this,
duration: Duration(seconds: 2),
);
// Tween определяет диапазон значений анимации.
_animation = Tween<double>(begin: 0, end: 2 * pi).animate(_controller);
_controller.repeat(); // Запускаем анимацию на повтор.
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _animation,
builder: (context, child) {
return Transform.rotate(
angle: _animation.value,
child: FlutterLogo(size: 100),
);
},
);
}
@override
void dispose() {
_controller.dispose(); // Важно: всегда освобождаем контроллер.
super.dispose();
}
}
Главное, ёпта, не забыть контроллер убить в dispose(), а то будет тебе утечка памяти — потом сам от себя охуеешь, куда оперативка делась.
3. Анимации на основе физики (Physics-based)
Это когда нужно, чтобы всё двигалось как в жизни — с пружинками, отскоками и гравитацией. Используешь SpringSimulation или GravitySimulation. Сделаешь шарик, который отскакивает от краёв — выглядит просто пиздец как круто.
4. Hero-анимации
Вот это вообще магия, ядрёна вошь! Нужно, чтобы картинка или виджет плавно переехали с одного экрана на другой? Hero тебе в помощь. Просто оборачиваешь виджет в два местах одним и тем же тегом, и Flutter сам сделает красивый переход.
// На первом экране
Hero(
tag: 'avatar', // Уникальный тег.
child: CircleAvatar(backgroundImage: NetworkImage(url)),
)
// На втором экране используем виджет с тем же тегом.
Hero(
tag: 'avatar',
child: Image.network(url, fit: BoxFit.cover),
)
Пользователь тыкает — и элемент летит через весь интерфейс. Удивление пиздец, честное слово.
5. Интеграция с Rive/Lottie
А это уже для дизайнеров, которые наваяли в Figme какую-нибудь дикую векторную анимацию. Не надо это всё вручную кодить — берёшь пакет rive или lottie, загружаешь готовый файл и наслаждаешься. Сидишь, кофе пьёшь, пока дизайнеры пашут.
А суть-то вся вот в чём: В Flutter анимация — это просто плавное изменение чисел, цветов и прочей хуйни с течением времени. Есть объект Animation, который говорит: «Сейчас значение вот такое». А виджеты на каждом кадре перерисовываются с этим новым значением. И получается движение. Всё гениальное — просто, как хуй с горы.