개발노트

62. [Flutter] CurvedAnimation (애니메이션 효과 시간에 굴곡 주기) 본문

앱 개발/Flutter

62. [Flutter] CurvedAnimation (애니메이션 효과 시간에 굴곡 주기)

mroh1226 2024. 1. 31. 14:28
반응형

CurvedAnimation 

  1. Curve 적용:
    • **CurvedAnimation**은 애니메이션을 제어하는데 사용되는 Animation 객체와 **Curve**를 인자로 받습니다. **Curve**는 애니메이션의 진행을 제어하는데 사용되며, 일반적으로 Curves 클래스에서 제공되는 미리 정의된 커브를 사용합니다.
  2. 보간(Interpolation):
    • **CurvedAnimation**은 주어진 **Curve**에 따라 애니메이션 값의 보간을 조절합니다. 예를 들어, **Curves.easeIn**을 사용하면 애니메이션은 천천히 시작하여 점차 속도를 증가시킵니다.
  3. 애니메이션 제어:
    • **CurvedAnimation**은 **AnimationController**와 함께 사용하여 애니메이션을 제어합니다. 이를 통해 애니메이션의 진행률과 속도를 조절할 수 있습니다.
    • parent: 속성에 animationController 를 넣어주고, Animation.animate(curve) 안에 curve 를 넣어줍니다.

CurvedAnimation 사용 예시

아래 예시 소스는 이전 포스팅의 AnimationBuilder 예시에 CurvedAnimation을 추가한 예시입니다.

- 이전 포스팅: https://mroh1226.tistory.com/173

 

61. [Flutter] AnimatedBuilder (명시적인 애니메이션 위젯이 없을 때 사용) with Tween

AnimatedBuilder AnimatedBuilder는 애니메이션을 지속적으로 업데이트하면서 UI를 리빌드할 때 사용됩니다. 이 위젯은 애니메이션의 값이 변경될 때마다 특정한 위젯을 다시 그려주기 때문에 애니메이

mroh1226.tistory.com


 

CurvedAnimation 예시 소스.
import 'package:flutter/material.dart';

class ExplicitAnimationScreen extends StatefulWidget {
  const ExplicitAnimationScreen({super.key});
  static String routeName = "explicitanimation";
  static String routeURL = "explicitanimation";

  @override
  State<ExplicitAnimationScreen> createState() =>
      _ExplicitAnimationScreenState();
}

class _ExplicitAnimationScreenState extends State<ExplicitAnimationScreen>
//SingleTickerProviderStateMixin -> Ticker가 하나만 필요할 때
//TickerProviderStateMixin -> Ticker가 여러개 필요할 떄
    with
        SingleTickerProviderStateMixin {
  late final AnimationController _animationController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 2000),
      reverseDuration: const Duration(milliseconds: 1000)
      //lowerBound: 50,      upperBound: 100
      );

  late final Animation<Color?> _color =
      ColorTween(begin: Colors.amber, end: Colors.blue).animate(_curve);

  late final Animation<Decoration> _decoration = DecorationTween(
          begin: const BoxDecoration(color: Colors.amber),
          end: const BoxDecoration(color: Colors.red))
      .animate(_curve);

  late final Animation<Offset> _transition =
      Tween(begin: const Offset(0, 0), end: const Offset(20, 20))
          .animate(_curve);

  late final Animation<double> _scale =
      Tween(begin: 0.0, end: 0.5).animate(_curve);

  late final CurvedAnimation _curve = CurvedAnimation(
      parent: _animationController,
      curve: Curves.elasticOut,
      reverseCurve: Curves.easeInOutExpo);

  @override
  void initState() {
    _animationController.addListener(() {});
    super.initState();
    // //Ticker는 애니메이션 프레임 하나당 한번 호출됨
    // Ticker((elapsed) {
    //   print(elapsed);
    // });
  }

  void _play() {
    _animationController.forward();
  }

  void _pause() {
    _animationController.stop();
  }

  void _reverse() {
    _animationController.reverse();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        elevation: 0,
        title: const Text("Explicit Animations"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            //AnimatedBuilder를 사용하면 화면 전체가 빌드되지않고 builder안에 있는 위젯만 리빌드됨
            AnimatedBuilder(
              animation: _animationController,
              builder: (context, child) {
                return Text("${_animationController.value}");
              },
            ),
            AnimatedBuilder(
              animation: _color,
              builder: (context, child) {
                return Transform.translate(
                  offset: _transition.value,
                  child: Container(
                    color: _color.value,
                    width: 100,
                    height: 100,
                  ),
                );
              },
            ),
            AnimatedBuilder(
              animation: _decoration,
              builder: (context, child) {
                return Transform.scale(
                  scale: _scale.value,
                  child: Container(
                    height: 100,
                    width: 100,
                    decoration: _decoration.value,
                  ),
                );
              },
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                ElevatedButton(onPressed: _play, child: const Text("Play")),
                ElevatedButton(onPressed: _pause, child: const Text("pause")),
                ElevatedButton(
                    onPressed: _reverse, child: const Text("reverse")),
              ],
            )
          ],
        ),
      ),
    );
  }
}

 


소스설명.
// 애니메이션 컨트롤러 생성
late final AnimationController _animationController = AnimationController(
  vsync: this, // vsync에는 TickerProvider를 전달하여 애니메이션을 동기화합니다.
  duration: const Duration(milliseconds: 2000), // 애니메이션의 기본 지속 시간 설정
  reverseDuration: const Duration(milliseconds: 1000), // 애니메이션의 역 방향 지속 시간 설정
);

// CurvedAnimation에 parent 속성에 애니메이션 컨트롤러 입력
late final CurvedAnimation _curve = CurvedAnimation(
  parent: _animationController, // 애니메이션 컨트롤러를 CurvedAnimation의 부모로 설정
  curve: Curves.elasticOut, // 애니메이션 진행에 적용할 곡선 지정
  reverseCurve: Curves.easeInOutExpo, // 애니메이션 역 방향 진행에 적용할 곡선 지정
);

// Animation의 .animate() 메서드에 curve 입력
late final Animation<double> _scale = Tween(begin: 0.0, end: 0.5).animate(_curve);

 

 

 

반응형
Comments