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

Как устроен Tween?

2.0 Middle🔥 151 комментариев
#Анимации

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

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

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

Как устроен Tween

Tween (от слова "in between") — это объект в Flutter, который интерполирует значение между начальным и конечным состоянием. Это основной механизм для создания плавных анимаций.

Принцип работы

Tween берёт значение от 0 до 1 (из AnimationController) и преобразует его в нужный диапазон значений:

AnimationController: 0.0 → 0.5 → 1.0
        |
        v
    Tween (100 → 300)
        |
        v
Значение: 100 → 200 → 300

Формула: value = begin + (end - begin) * progress

Базовые типы Tween

1. Tween<T>

Общий Tween для любых типов с поддержкой lerp (линейная интерполяция):

final tweenColor = Tween<Color?>(
  begin: Colors.blue,
  end: Colors.red,
);

final animation = _controller.drive(tweenColor);

2. ColorTween

final colorTween = ColorTween(
  begin: Colors.white,
  end: Colors.black,
);

3. Tween<double>

final sizeTween = Tween<double>(
  begin: 0.0,
  end: 100.0,
);

4. RectTween, SizeTween и другие специализированные

Использование Tween с AnimationController

class _AnimatedBoxState extends State<AnimatedBox>
    with TickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _animation;

  @override
  void initState() {
    super.initState();
    
    // Создаём контроллер
    _controller = AnimationController(
      duration: Duration(seconds: 2),
      vsync: this,
    );
    
    // Создаём Tween и привязываем к контроллеру
    _animation = Tween<double>(begin: 0.0, end: 300.0)
        .animate(_controller);
    
    _controller.forward();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _animation,
      builder: (context, child) {
        return Transform.translate(
          offset: Offset(_animation.value, 0),
          child: Container(
            width: 50,
            height: 50,
            color: Colors.blue,
          ),
        );
      },
    );
  }
}

Цепочка Tween'ов

// Tween.chain объединяет несколько Tween'ов
final animation = Tween<double>(begin: 0.0, end: 1.0).chain(
  CurveTween(curve: Curves.easeInOut),
).animate(_controller);

Использование с Curves

// CurveTween для применения кривой анимации
final animation = _controller.drive(
  Tween<double>(begin: 0.0, end: 100.0).chain(
    CurveTween(curve: Curves.bounceOut),
  ),
);

Расширенный пример: Меняющийся цвет и размер

class ComplexAnimation extends StatefulWidget {
  @override
  State<ComplexAnimation> createState() => _ComplexAnimationState();
}

class _ComplexAnimationState extends State<ComplexAnimation>
    with TickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _sizeAnimation;
  late Animation<Color?> _colorAnimation;
  late Animation<double> _rotationAnimation;

  @override
  void initState() {
    super.initState();
    
    _controller = AnimationController(
      duration: Duration(seconds: 3),
      vsync: this,
    );
    
    // Размер: 50 → 200
    _sizeAnimation = Tween<double>(begin: 50.0, end: 200.0)
        .animate(_controller);
    
    // Цвет: синий → красный
    _colorAnimation = ColorTween(
      begin: Colors.blue,
      end: Colors.red,
    ).animate(_controller);
    
    // Ротация: 0 → 360 градусов
    _rotationAnimation = Tween<double>(begin: 0.0, end: 1.0)
        .animate(_controller);
    
    _controller.repeat(reverse: true);
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: AnimatedBuilder(
        animation: _controller,
        builder: (context, child) {
          return Transform.rotate(
            angle: _rotationAnimation.value * 2 * 3.14159,
            child: Container(
              width: _sizeAnimation.value,
              height: _sizeAnimation.value,
              decoration: BoxDecoration(
                color: _colorAnimation.value,
                shape: BoxShape.circle,
              ),
            ),
          );
        },
      ),
    );
  }
}

Важные концепции

  • Tween.animate() — привязывает Tween к Animation
  • drive() — альтернативный способ привязки
  • lerp() — метод линейной интерполяции
  • transform() — кастомная трансформация значения
  • Stateless анимация с Tween — самый эффективный способ

Сравнение подходов

// 1. Tween + AnimatedBuilder (лучший способ)
Tween<double>(begin: 0, end: 100).animate(_controller)

// 2. Explicit Animation
AnimatedContainer(duration: Duration(seconds: 1))

// 3. Implicit Animation  
AnimatedPositioned(duration: Duration(seconds: 1))

Tween — это фундамент всех анимаций во Flutter. Понимание его работы критически важно для создания гладких, эффективных UI взаимодействий.