← Назад к вопросам

Что такое явные анимации?

1.7 Middle🔥 172 комментариев
#Flutter виджеты#Анимации

Комментарии (2)

🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Явные анимации в Flutter

Явные анимации (Explicit Animations) — это анимации, которые вы полностью контролируете через AnimationController. В отличие от неявных анимаций (implicit), вы сами управляете началом, длительностью и прогрессом анимации.

Явные vs Неявные анимации

Неявные анимации — это просто:

// Неявная анимация: просто меняем свойство
AnimatedContainer(
  duration: Duration(seconds: 1),
  width: isExpanded ? 200 : 100,
  height: isExpanded ? 200 : 100,
  color: Colors.blue,
)

Явные анимации — полный контроль:

// Явная анимация: мы управляем всем
AnimationController controller = AnimationController(
  duration: Duration(seconds: 1),
  vsync: this,
);
controller.forward(); // начало
controller.reverse(); // отмена
controller.stop();    // остановка

Основные компоненты

  1. AnimationController — управляет анимацией
  2. Animation — описывает значение анимации
  3. Tween — диапазон значений (от...до)
  4. Curve — кривая анимации (ускорение, замедление)

Пример 1: Простая явная анимация

class ExplicitAnimationExample extends StatefulWidget {
  @override
  State<ExplicitAnimationExample> createState() => _ExplicitAnimationExampleState();
}

class _ExplicitAnimationExampleState extends State<ExplicitAnimationExample>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _animation;
  
  @override
  void initState() {
    super.initState();
    
    // Создаём controller
    _controller = AnimationController(
      duration: Duration(seconds: 2),
      vsync: this, // требуется TickerProvider
    );
    
    // Создаём анимацию от 0 к 200
    _animation = Tween<double>(begin: 0, end: 200).animate(
      CurvedAnimation(parent: _controller, curve: Curves.easeInOut),
    );
  }
  
  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
  
  void _startAnimation() {
    _controller.forward();
  }
  
  void _reverseAnimation() {
    _controller.reverse();
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            // AnimatedBuilder перестраивается при изменении animation
            AnimatedBuilder(
              animation: _animation,
              builder: (context, child) {
                return Container(
                  width: _animation.value,
                  height: _animation.value,
                  color: Colors.blue,
                );
              },
            ),
            SizedBox(height: 30),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                ElevatedButton(
                  onPressed: _startAnimation,
                  child: Text('Начать'),
                ),
                SizedBox(width: 10),
                ElevatedButton(
                  onPressed: _reverseAnimation,
                  child: Text('Отмена'),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

Пример 2: Анимация поворота

class RotationAnimationExample extends StatefulWidget {
  @override
  State<RotationAnimationExample> createState() => _RotationAnimationExampleState();
}

class _RotationAnimationExampleState extends State<RotationAnimationExample>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  
  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: Duration(seconds: 2),
      vsync: this,
    );
  }
  
  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            // RotationTransition использует встроенную поддержку поворота
            RotationTransition(
              turns: _controller, // от 0 к 1 (0 к 360 градусам)
              child: Container(
                width: 100,
                height: 100,
                color: Colors.red,
              ),
            ),
            SizedBox(height: 30),
            ElevatedButton(
              onPressed: () {
                _controller.forward();
              },
              child: Text('Вращать'),
            ),
          ],
        ),
      ),
    );
  }
}

Пример 3: Несколько анимаций одновременно

class MultipleAnimationsExample extends StatefulWidget {
  @override
  State<MultipleAnimationsExample> createState() => _MultipleAnimationsExampleState();
}

class _MultipleAnimationsExampleState extends State<MultipleAnimationsExample>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _scaleAnimation;
  late Animation<double> _opacityAnimation;
  late Animation<Offset> _slideAnimation;
  
  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: Duration(seconds: 1),
      vsync: this,
    );
    
    // Масштабирование
    _scaleAnimation = Tween<double>(begin: 0.5, end: 1.5).animate(
      CurvedAnimation(parent: _controller, curve: Curves.elasticInOut),
    );
    
    // Прозрачность
    _opacityAnimation = Tween<double>(begin: 0, end: 1).animate(
      CurvedAnimation(parent: _controller, curve: Curves.easeIn),
    );
    
    // Смещение
    _slideAnimation = Tween<Offset>(
      begin: Offset(-1, 0),
      end: Offset(0, 0),
    ).animate(
      CurvedAnimation(parent: _controller, curve: Curves.easeOut),
    );
  }
  
  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            AnimatedBuilder(
              animation: _controller,
              builder: (context, child) {
                return SlideTransition(
                  position: _slideAnimation,
                  child: Opacity(
                    opacity: _opacityAnimation.value,
                    child: Transform.scale(
                      scale: _scaleAnimation.value,
                      child: Container(
                        width: 100,
                        height: 100,
                        color: Colors.green,
                      ),
                    ),
                  ),
                );
              },
            ),
            SizedBox(height: 30),
            ElevatedButton(
              onPressed: () => _controller.forward(),
              child: Text('Анимировать'),
            ),
          ],
        ),
      ),
    );
  }
}

Встроенные Transition виджеты

// Flutter предоставляет готовые Transition компоненты
ScaleTransition(scale: animation, child: widget);
RotationTransition(turns: animation, child: widget);
SlideTransition(position: animation, child: widget);
FadeTransition(opacity: animation, child: widget);
SizeTransition(sizeFactor: animation, child: widget);

Пример 4: Повторяющаяся анимация

class RepeatingAnimationExample extends StatefulWidget {
  @override
  State<RepeatingAnimationExample> createState() => _RepeatingAnimationExampleState();
}

class _RepeatingAnimationExampleState extends State<RepeatingAnimationExample>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  
  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: Duration(seconds: 1),
      vsync: this,
    );
    
    // Повторять анимацию бесконечно
    _controller.repeat(reverse: true); // туда-сюда
  }
  
  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ScaleTransition(
          scale: Tween<double>(begin: 0.8, end: 1.2).animate(_controller),
          child: Container(
            width: 100,
            height: 100,
            color: Colors.purple,
          ),
        ),
      ),
    );
  }
}

Контроль анимации

// Методы AnimationController
_controller.forward();      // начало (от 0 к 1)
_controller.reverse();      // отмена (от 1 к 0)
_controller.stop();         // остановка
_controller.reset();        // сброс на начало
_controller.forward(from: 0.5); // начало с позиции 0.5
_controller.repeat();       // повторять
_controller.repeat(reverse: true); // туда-сюда

// Слушатели
_controller.addListener(() {
  print('Значение: ${_controller.value}'); // от 0 к 1
});

_controller.addStatusListener((status) {
  if (status == AnimationStatus.completed) {
    print('Анимация завершена');
  }
});

Когда использовать явные анимации

  • Нужен полный контроль над анимацией
  • Сложные анимации с несколькими этапами
  • Анимации по действиям пользователя
  • Требуется слушатель для срабатывания действий
  • Необходимо управление временем (пауза, продолжение)

Явные анимации — это мощный инструмент для создания сложных и управляемых анимаций в Flutter.