관리 메뉴

Bull

[Flutter::Animation] Fade 기법 본문

Software Framework/Flutter

[Flutter::Animation] Fade 기법

Bull_ 2024. 7. 25. 06:57

Fade 란?

Flutter에서 사용되는 Fade 기법은 자주 사용되는 애니메이션 기법 중 하나로 이름처럼 직관적인 개념을 나타냅니다. 위젯의 사라짐과 나타냄을 부드럽게 표현할 수 있습니다. 이를 opacity 프로퍼티에 애니메이션을 적용하여 나타낼 수 있습니다. implicit animations에서 AnimatedOpacity 위젯이 있습니다. 이 위젯은 opacity 프로퍼티를 관측하고 그 값이 변화할 때 애니메이션 효과를 넣어 줄 수 있습니다.

 

Flutter 공식문서의 Tutorial에 따르면 Fade의 개념을 AnimatedOpacity를 사용하여 설명합니다.

CODE

공식문서에서 제공된 CODE는 다음과 같습니다.

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    const appTitle = 'Opacity Demo';
    return const MaterialApp(
      title: appTitle,
      home: MyHomePage(title: appTitle),
    );
  }
}

// The StatefulWidget's job is to take data and create a State class.
// In this case, the widget takes a title, and creates a _MyHomePageState.
class MyHomePage extends StatefulWidget {
  const MyHomePage({
    super.key,
    required this.title,
  });

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

// The State class is responsible for two things: holding some data you can
// update and building the UI using that data.
class _MyHomePageState extends State<MyHomePage> {
  // Whether the green box should be visible
  bool _visible = true;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: AnimatedOpacity(
          // If the widget is visible, animate to 0.0 (invisible).
          // If the widget is hidden, animate to 1.0 (fully visible).
          opacity: _visible ? 1.0 : 0.0,
          duration: const Duration(milliseconds: 500),
          // The green box must be a child of the AnimatedOpacity widget.
          child: Container(
            width: 200,
            height: 200,
            color: Colors.green,
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          // Call setState. This tells Flutter to rebuild the
          // UI with the changes.
          setState(() {
            _visible = !_visible;
          });
        },
        tooltip: 'Toggle Opacity',
        child: const Icon(Icons.flip),
      ),
    );
  }
}

결과 창은 생략하겠습니다.

 

버튼을 누르면 setState로 값을 관리하여 바뀜과 동시에 AnimatedOpacityopacity를 관측하고 변하는 opacity에 애니메이션 효과를 부여합니다.

 

하지만 implicit animation은 프로퍼티를 통해 간단한 애니메이션을 주고 싶을 때 주로 사용하는 개념으로 알고 있습니다. 따라서 세세한 애니메이션을 컨트롤을 하려면 컨트롤러가 필요할 텐데요. 자주 사용하는 Fade 기법에 Controller를 부여하기 위해 Flutter는 다음 위젯을 제공해줍니다.

FadeTransition

FadeTransition 위젯은 AnimatedOpacity로 위젯의 opacity를 조정한 것과 같은 역할을 수행합니다. 즉 사라짐과 나타냄에 애니메이션 효과를 부여합니다. 둘의 차이로 FadeTransition는 Controller를 사용할 수 있습니다. 컨트롤러가 추가됨에 따라 애니메이션을 컨트롤할 수 있게 됩니다.

 

예제와 함께 살펴보겠습니다.

CODE

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Fade Animation Example')),
        body: FadeDemo(),
      ),
    );
  }
}

class FadeDemo extends StatefulWidget {
  @override
  _FadeDemoState createState() => _FadeDemoState();
}

class _FadeDemoState extends State<FadeDemo> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(seconds: 2),
      vsync: this,
    );
    _animation = CurvedAnimation(parent: _controller, curve: Curves.easeIn);
  }

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

  void _startAnimation() {
    _controller.forward();
  }

  void _stopAnimation() {
    _controller.stop();
  }

  void _reverseAnimation() {
    _controller.reverse();
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          FadeTransition(
            opacity: _animation,
            child: Container(
              width: 200,
              height: 200,
              color: Colors.blue,
            ),
          ),
          SizedBox(height: 20),
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ElevatedButton(
                onPressed: _startAnimation,
                child: Text('Start'),
              ),
              SizedBox(width: 10),
              ElevatedButton(
                onPressed: _stopAnimation,
                child: Text('Stop'),
              ),
              SizedBox(width: 10),
              ElevatedButton(
                onPressed: _reverseAnimation,
                child: Text('Reverse'),
              ),
            ],
          ),
        ],
      ),
    );
  }
}

late AnimationController _controller; 를 통해 컨트롤러를 정의하고

    _controller = AnimationController(
      duration: const Duration(seconds: 2),
      vsync: this,
    );

AnimationController을 통해 컨트롤러를 초기화 하였습니다. forward(), stop(), remove() 등 컨트롤러의 메소드를 통해 애니메이션을 조작할 수 있습니다. 이를

  void _startAnimation() {
    _controller.forward();
  }

  void _stopAnimation() {
    _controller.stop();
  }

  void _reverseAnimation() {
    _controller.reverse();
  }

(... CODE ...)

              ElevatedButton(
                onPressed: _startAnimation,
                child: Text('Start'),
              ),
              SizedBox(width: 10),
              ElevatedButton(
                onPressed: _stopAnimation,
                child: Text('Stop'),
              ),
              SizedBox(width: 10),
              ElevatedButton(
                onPressed: _reverseAnimation,
                child: Text('Reverse'),
              ),

와 같이 버튼을 누르면 해당 역할을 수행할 수 있도록 메소드로 구현하였습니다.

다른 Fade 관련 클래스

AnimatedOpacity도 있지만 앞서 소개하지 않은 SliverFadeTransitionFadeInImage 클래스도 있습니다.

 

SliverFadeTransitionCustomScrollViewSliverList, SliverGrid와 같은 Sliver 위젯에서 사용할 수 있는 Fade 애니메이션을 제공합니다. 이 위젯은 일반적인 FadeTransition과 비슷하지만, Sliver 위젯에 특화되어 있습니다.

 

FadeInImage는 네트워크 이미지나 자산 이미지를 불러올 때, 로딩 중인 동안 다른 이미지로 대체하는 동안 Fade 애니메이션을 제공합니다.

 

다른 클래스가 더 있는지는 제가 찾아보지 않았으나 직접 예제를 통해 사용하여 익히면 애니메이션을 사용하는데 도움될 것입니다.

참고 자료