본문 바로가기
프로그래밍/Flutter

[Flutter] 9. Flutter의 "애니메이션 및 그래픽"

by iwbap 2024. 6. 26.
728x90

Flutter 학습: 애니메이션 및 그래픽

Flutter에서는 다양한 애니메이션과 그래픽을 쉽게 구현할 수 있는 기능을 제공합니다. 이번 글에서는 기본 애니메이션, 고급 애니메이션, 그리고 커스텀 페인터를 사용한 그림 그리기에 대해 알아보겠습니다.


1. 기본 애니메이션: Animation, AnimationController, Tween

기본 애니메이션을 구현하기 위해서는 Animation, AnimationController, Tween을 사용합니다. AnimationController는 애니메이션의 실행과 제어를 담당하고, Tween은 시작 값과 끝 값을 정의하여 애니메이션의 변화를 설정합니다.

 

기본 애니메이션 예제: 간단한 애니메이션을 통해 버튼을 누를 때마다 크기가 변하는 애니메이션을 구현해보겠습니다.

[dart]
 
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: AnimationExample(),
    );
  }
}

class AnimationExample extends StatefulWidget {
  @override
  _AnimationExampleState createState() => _AnimationExampleState();
}

class _AnimationExampleState extends State<AnimationExample> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _animation;

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

    _animation = Tween<double>(begin: 0, end: 300).animate(_controller)
      ..addListener(() {
        setState(() {});
      });

    _controller.forward();
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Basic Animation Example'),
      ),
      body: Center(
        child: Container(
          width: _animation.value,
          height: _animation.value,
          color: Colors.blue,
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          if (_controller.isCompleted) {
            _controller.reverse();
          } else {
            _controller.forward();
          }
        },
        child: Icon(Icons.play_arrow),
      ),
    );
  }
}
 

위의 예제에서 AnimationController와 Tween을 사용하여 버튼을 누를 때마다 애니메이션이 실행되고, Container의 크기가 변합니다.


2. 고급 애니메이션: AnimatedBuilder, Hero 애니메이션, Staggered 애니메이션

AnimatedBuilder: AnimatedBuilder는 애니메이션을 효율적으로 구성하기 위해 사용되는 위젯으로, 애니메이션의 빌드 함수를 정의합니다.

 

AnimatedBuilder 예제:

[dart]
 
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: AnimatedBuilderExample(),
    );
  }
}

class AnimatedBuilderExample extends StatefulWidget {
  @override
  _AnimatedBuilderExampleState createState() => _AnimatedBuilderExampleState();
}

class _AnimatedBuilderExampleState extends State<AnimatedBuilderExample> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _animation;

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

    _animation = Tween<double>(begin: 0, end: 300).animate(_controller);
    _controller.forward();
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('AnimatedBuilder Example'),
      ),
      body: Center(
        child: AnimatedBuilder(
          animation: _animation,
          builder: (context, child) {
            return Container(
              width: _animation.value,
              height: _animation.value,
              color: Colors.blue,
            );
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          if (_controller.isCompleted) {
            _controller.reverse();
          } else {
            _controller.forward();
          }
        },
        child: Icon(Icons.play_arrow),
      ),
    );
  }
}
 
 

Hero 애니메이션: Hero 위젯은 두 화면 간의 전환 애니메이션을 쉽게 구현할 수 있게 해줍니다.

 

Hero 애니메이션 예제:

[dart]
 
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: FirstScreen(),
    );
  }
}

class FirstScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('First Screen'),
      ),
      body: Center(
        child: GestureDetector(
          onTap: () {
            Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => SecondScreen()),
            );
          },
          child: Hero(
            tag: 'hero-example',
            child: Container(
              width: 100,
              height: 100,
              color: Colors.blue,
            ),
          ),
        ),
      ),
    );
  }
}

class SecondScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Second Screen'),
      ),
      body: Center(
        child: Hero(
          tag: 'hero-example',
          child: Container(
            width: 300,
            height: 300,
            color: Colors.blue,
          ),
        ),
      ),
    );
  }
}
 
 

Staggered 애니메이션: Staggered 애니메이션은 여러 애니메이션을 순차적으로 실행하는 방법입니다.

 

Staggered 애니메이션 예제:

[dart]
 
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: StaggeredAnimationExample(),
    );
  }
}

class StaggeredAnimationExample extends StatefulWidget {
  @override
  _StaggeredAnimationExampleState createState() => _StaggeredAnimationExampleState();
}

class _StaggeredAnimationExampleState extends State<StaggeredAnimationExample> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _animation1;
  late Animation<double> _animation2;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(seconds: 4),
      vsync: this,
    );

    _animation1 = Tween<double>(begin: 0, end: 200).animate(
      CurvedAnimation(parent: _controller, curve: Interval(0.0, 0.5, curve: Curves.easeIn)),
    );

    _animation2 = Tween<double>(begin: 0, end: 200).animate(
      CurvedAnimation(parent: _controller, curve: Interval(0.5, 1.0, curve: Curves.easeOut)),
    );

    _controller.forward();
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Staggered Animation Example'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            AnimatedBuilder(
              animation: _animation1,
              builder: (context, child) {
                return Container(
                  width: _animation1.value,
                  height: 50,
                  color: Colors.blue,
                );
              },
            ),
            SizedBox(height: 20),
            AnimatedBuilder(
              animation: _animation2,
              builder: (context, child) {
                return Container(
                  width: _animation2.value,
                  height: 50,
                  color: Colors.red,
                );
              },
            ),
          ],
        ),
      ),
    );
  }
}

3. 커스텀 페인터: CustomPainter, 그림 그리기

Flutter에서는 CustomPainter를 사용하여 화면에 직접 그림을 그릴 수 있습니다. CustomPainter는 복잡한 그래픽을 그리기 위해 사용됩니다.

 

CustomPainter 사용 예제:

[dart]
 
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: CustomPainterExample(),
    );
  }
}

class CustomPainterExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('CustomPainter Example'),
      ),
      body: Center(
        child: CustomPaint(
          size: Size

 

728x90