본문 바로가기
Flutter

Flutter에서의 커스텀 애니메이션 적용하기

by 안될개발 2025. 3. 2.

Flutter에서의 커스텀 애니메이션 적용하기

Flutter에서의 커스텀 애니메이션 적용하기

Flutter에서는 애니메이션을 쉽게 구현할 수 있도록 다양한 도구를 제공합니다. 기본적으로 AnimatedContainer나 AnimatedOpacity 같은 내장 위젯을 사용할 수도 있지만, 더 정교한 애니메이션을 만들기 위해서는 AnimationController, Tween, CustomPainter 등을 활용한 커스텀 애니메이션이 필요합니다.

이번 글에서는 Flutter에서 커스텀 애니메이션을 구현하는 방법을 단계별로 설명하고, 실전에서 자주 활용할 수 있는 예제들을 소개하겠습니다.


1. 애니메이션의 기본 개념

Flutter에서 애니메이션은 시간의 흐름에 따라 UI의 속성을 변경하는 것을 의미합니다. 주요 개념은 다음과 같습니다:

  • Animation: 시간의 흐름에 따라 값이 변하는 객체
  • AnimationController: 애니메이션을 시작, 중지, 되감기 등의 제어하는 컨트롤러
  • Tween: 애니메이션의 시작값과 끝값을 설정하는 보간기
  • Curves: 애니메이션의 속도 곡선을 정의하는 클래스 (e.g., Curves.easeInOut)
  • Ticker: 애니메이션을 프레임 단위로 실행하도록 하는 타이밍 메커니즘

Flutter에서 애니메이션을 구현하는 가장 기본적인 방법은 AnimationController와 Tween을 사용하는 것입니다.


2. AnimationController를 활용한 기본 애니메이션

AnimationController는 애니메이션의 진행 상태를 직접 제어할 수 있는 컨트롤러입니다.

예제: 크기가 커졌다 작아지는 애니메이션

import 'package:flutter/material.dart';

class ScaleAnimation extends StatefulWidget {
  @override
  _ScaleAnimationState createState() => _ScaleAnimationState();
}

class _ScaleAnimationState extends State<ScaleAnimation>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      vsync: this,
      duration: Duration(seconds: 2),
    )..repeat(reverse: true);

    _animation = Tween<double>(begin: 1.0, end: 1.5).animate(
      CurvedAnimation(parent: _controller, curve: Curves.easeInOut),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: AnimatedBuilder(
          animation: _animation,
          builder: (context, child) {
            return Transform.scale(
              scale: _animation.value,
              child: Container(
                width: 100,
                height: 100,
                color: Colors.blue,
              ),
            );
          },
        ),
      ),
    );
  }

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

이 코드에서는 AnimationController와 Tween을 이용해 크기가 1.0에서 1.5까지 변하는 애니메이션을 구현했습니다.


3. TweenSequence를 활용한 다단계 애니메이션

여러 개의 트윈을 조합하여 복합적인 애니메이션을 만들 수도 있습니다.

예제: 크기가 점진적으로 변하는 애니메이션

_animation = TweenSequence([
  TweenSequenceItem(tween: Tween(begin: 1.0, end: 1.2), weight: 50),
  TweenSequenceItem(tween: Tween(begin: 1.2, end: 0.8), weight: 50),
  TweenSequenceItem(tween: Tween(begin: 0.8, end: 1.0), weight: 50),
]).animate(_controller);

위 코드는 크기가 1.0 → 1.2 → 0.8 → 1.0 순서로 변화하는 애니메이션을 구현합니다.


4. CustomPainter를 활용한 커스텀 애니메이션

CustomPainter를 사용하면 더욱 자유로운 애니메이션을 만들 수 있습니다.

예제: 원이 점점 커지는 애니메이션

class CirclePainter extends CustomPainter {
  final double radius;
  CirclePainter(this.radius);

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = Colors.blue
      ..style = PaintingStyle.fill;
    canvas.drawCircle(size.center(Offset.zero), radius, paint);
  }

  @override
  bool shouldRepaint(CirclePainter oldDelegate) => oldDelegate.radius != radius;
}

이제 AnimationController를 사용해 radius 값을 애니메이션으로 조정할 수 있습니다.

class CircleAnimation extends StatefulWidget {
  @override
  _CircleAnimationState createState() => _CircleAnimationState();
}

class _CircleAnimationState extends State<CircleAnimation> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _radiusAnimation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(vsync: this, duration: Duration(seconds: 2))..repeat(reverse: true);
    _radiusAnimation = Tween<double>(begin: 10.0, end: 50.0).animate(_controller);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: AnimatedBuilder(
          animation: _radiusAnimation,
          builder: (context, child) {
            return CustomPaint(
              size: Size(100, 100),
              painter: CirclePainter(_radiusAnimation.value),
            );
          },
        ),
      ),
    );
  }

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

5. 결론

Flutter에서는 AnimationController, Tween, CustomPainter 등을 활용하여 강력한 커스텀 애니메이션을 구현할 수 있습니다.

  • AnimationController: 애니메이션의 타이밍을 제어
  • Tween: 값의 보간을 담당
  • Curves: 자연스러운 애니메이션 효과 추가
  • CustomPainter: 복잡한 UI 애니메이션 구현 가능

Flutter에서 애니메이션을 효과적으로 활용하면 UX를 크게 향상시킬 수 있습니다.

앞으로 프로젝트에서 애니메이션을 적극적으로 활용해보시기 바랍니다.