Расскажи про анимации в Flutter.

Ответ

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, который говорит: «Сейчас значение вот такое». А виджеты на каждом кадре перерисовываются с этим новым значением. И получается движение. Всё гениальное — просто, как хуй с горы.