Flutter - #30. AnimatedOpacity, FadeTransition

Pearl Lee·2021년 7월 7일
0

Flutter Widget

목록 보기
29/50

내가 보려고 쓰는 Flutter 일기
참고1 : https://api.flutter.dev/flutter/widgets/AnimatedOpacity-class.html
참고2 : https://api.flutter.dev/flutter/widgets/ImplicitlyAnimatedWidget-class.html
참고3 : https://api.flutter.dev/flutter/widgets/AnimatedWidget-class.html









AnimatedOpacity

오늘 배워볼 건 Opacity(투명도) 조절에 애니메이션 효과를 주는 AnimatedOpacity.
지난 시간 여러번 해본 Animation 과 사용법은 비슷하다. duration과 child, curve등을 주면 되는 것! 변화하는 값은 opacity에 설정한다.
0 이면 투명, 1이면 불투명이다. 즉 0이면 사라진다.
간단하니 바로 코드로 넘어가자.









코드 예시로 알아보자

공식 페이지 코드 가져다가 조금만 수정해주었다. 공식 문서 코드는 맨날 위젯 크기가 너무 작아...

import 'package:flutter/material.dart';

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

/// This is the main application widget.
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  static const String _title = 'Test AnimatedOpacity';

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: _title,
      home: Scaffold(
        appBar: AppBar(title: const Text(_title)),
        body: AnimatedOpacityWidget(),
      ),
    );
  }
}

class AnimatedOpacityWidget extends StatefulWidget {
  const AnimatedOpacityWidget({Key? key}) : super(key: key);

  
  State<AnimatedOpacityWidget> createState() => AnimatedOpacityWidgetState();
}

class AnimatedOpacityWidgetState extends State<AnimatedOpacityWidget> {
  double opacityLevel = 1.0;

  
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          AnimatedOpacity(
            curve: Curves.fastOutSlowIn,
            opacity: opacityLevel,
            duration: const Duration(seconds: 3),
            child: SizedBox(
              child: const FlutterLogo(),
              height: 200,
              width: 200,
            ),
          ),
          ElevatedButton(
            child: const Text('Fade Logo'),
            onPressed: () {
              setState(() => opacityLevel = opacityLevel == 0 ? 1.0 : 0.0);
            },
          ),
        ],
      ),
    );
  }
}

ElevatedButton을 누르면 투명도가 변화하도록, onPressed안에 setState를 넣어서 변화를 설정한다. 실행화면은 아래와 같다.




그런데 공식 페이지를 뒤집다 보니, AnimatedOpacity와 거의 동일한 기능을 하는 아이를 발견했다. 바로 FadeTransition이다.






FadeTransition

위의 AnimatedOpacity 코드 실행과 똑같이 보이도록, 공식 페이지의 코드를 일부 수정해서 돌려보았다.

import 'package:flutter/material.dart';

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

/// This is the main application widget.
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  static const String _title = 'Flutter Code Sample';

  
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: _title,
      home: FadeTransitionWidget(),
    );
  }
}

/// This is the stateful widget that the main application instantiates.
class FadeTransitionWidget extends StatefulWidget {
  const FadeTransitionWidget({Key? key}) : super(key: key);

  
  State<FadeTransitionWidget> createState() => _FadeTransitionWidgetState();
}

/// This is the private State class that goes with MyStatefulWidget.
/// AnimationControllers can be created with `vsync: this` because of TickerProviderStateMixin.
class _FadeTransitionWidgetState extends State<FadeTransitionWidget>
    with SingleTickerProviderStateMixin {
  late final AnimationController _controller = AnimationController(
    duration: const Duration(seconds: 3),
    vsync: this);
  
  late final Animation<double> _animation = CurvedAnimation(
    parent: _controller,
    curve: Curves.easeIn,
  );

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

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Test FadeTransition'),
      ),
      body: Container(
        color: Colors.white,
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              FadeTransition(
                opacity: _animation,
                child: SizedBox(width: 200, height: 200, child: FlutterLogo()),
              ),
              ElevatedButton(
                  onPressed: () {
                    if(_controller.isCompleted)
                      _controller.reverse();
                    else
                      _controller.forward();
                  },
                  child: Text('Fade Logo'))
            ],
          ),
        ),
      ),
    );
  }
}

forward, reverse 기능을 몰라서 한참 헤맸네. (사실 onPressed에 저렇게 써도 되는지도 모르겠다. 일단 돌아가면 괜찮은 거 아닐까!)
실행결과는 아래와 같다.








ImplicitlyAnimatedWidget vs AnimatedWidget

실행은 똑같이 되는데, 코드를 작성하는 방법이 다르다.
FadeTransition은 AnimationController 를 선언해서 사용하고, AnimatedOpacity는 컨트롤러 없이 사용해도 애니메이션을 구현한다.

AnimatedOpacity는 상위 추상 클래스로 ImplicitlyAnimatedWidget 클래스를 두고 있다. Implicit를 사전에 찾아보니, '내포된, 포함되는' 라는 뜻을 가지고 있다.

ImplicitlyAnimatedWidget 을 상속받는 클래스들은 변화를 감지하면 애니메이션을 구현하는데, 이를 처리하기 위해 내부적으로 AnimationController를 알아서 만들어 쓴다고 한다.



AnimationController를 쓰게되면 초기화 하고 나중에 안쓰면 dispose로 버려주는 등 수명 주기(lifecycle) 관리가 필요한데, ImplicitlyAnimatedWidget 를 상속받는 클래스들은 컨트롤러를 따로 안써도 되니 편리하다. 저번에 배웠던 AnimatedContainer, TweenAnimationBuilder 등이 여기에 속한다.

다만 duration, curve등의 속성을 선택해서 쓰고 그 안에서 한정되기 때문에, 좀 더 마음대로 애니메이션을 조절하려면 Controller를 사용해야 한다. 이 때는 AnimatedWidget 계열 클래스들을 쓰면 된다. FadeTransition과, 저번에 배워본 AnimatedBuilder 등이 여기에 속한다.

ImplicitlyAnimatedWidget | AnimatedWidget 요기 가면 설명이 있으니, 참고하면 된다!







제발 내가 맞게 이해하고 있는거면 좋겠다^^
오늘의 일기는 여기까지!

profile
안 되면 되게 하라

0개의 댓글