본문 바로가기
flutter/Widget of the Week

Flutter[플러터] / AnimatedSwitcher 를 사용하여 두개 이상의 위젯에 전환 애니메이션 넣기 (효과, animation, 스위치, 교체,화면 전환) AnimatedSwitcher (Flutter Widget of the Week)

by ch5c 2025. 5. 31.
반응형

AnimatedSwitcher class

기본적으로 AnimatedSwitcher 에 자식으로 설정된 위젯과 새 위젯 사이에 크로스 페이드를 수행하는 위젯입니다.

https://youtu.be/2W7POjFb88g

공식 문서 코드

 


AnimatedSwitcher 는 위젯 간의 전환 애니메이션을 손쉽게 구현할 수 있도록 도와주는 위젯이다. 사용하기 간단하니 한번 알아보자.

하위 속성
속성명 타입 기본값 설명
child Widget? 현재 표시할 자식 위젯
duration Duration 필수 새 자식 위젯이 들어올 때의 전환 지속 시간
reverseDuration Duration? null 기존 자식 위젯이 사라질 때의 전환 지속 시간
switchInCurve Curve Curves.linear 새 자식이 들어올 때 사용하는 애니메이션 곡선
switchOutCurve Curve Curves.linear 기존 자식이 사라질 때 사용하는 애니메이션 곡선
transitionBuilder AnimatedSwitcherTransitionBuilder AnimatedSwitcher.defaultTransitionBuilder 자식 위젯에 적용할 전환 애니메이션을 정의하는 함수
layoutBuilder AnimatedSwitcherLayoutBuilder AnimatedSwitcher.defaultLayoutBuilder 현재 자식과 이전 자식을 어떻게 배치할지 정의하는 함수

 

기본적인 구성은 이렇게 된다. child 에는 전환할 위젯을 넣어주고 duration 으로 속도 조절을, builder 함수에는 애니메이션을 넣어주면 된다.

AnimatedSwitcher(
  duration: Duration(milliseconds: 400),
  transitionBuilder: (child, animation) { // child, animation 파라미터를 사용!!
    return FadeTransition(opacity: animation, child: child,); // 애니메이션 위젯에 바로 넣기!
  },
  child: Container(),
)

 

일단 이름부터 Animated 들어갔으니 또 AnimationController 선언해주고.. 이런 거 할 줄 알았다면 경기도 오산이다. 예제 코드를 보면 알겠지만 애니메이션컨트롤러를 사용하지 않고 AnimatedSwitcher 의 함수인 transitonBuilder 안에 있는 인자값인 animation 을 넣어 주는 모습이다. 각설하고 코드를 봐보자. 

(전체코드)

import 'package:flutter/material.dart';

void main() => runApp(MaterialApp(home: Test()));

class Test extends StatefulWidget {
  const Test({super.key});

  @override
  State<Test> createState() => _TestState();
}

class _TestState extends State<Test> {
  int _count = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          children: [
            AnimatedSwitcher(
              duration: Duration(milliseconds: 400),
                transitionBuilder: (child, animation) {
                  return FadeTransition(opacity: animation, child: child,);
                },
                child: Text('$_count', key: ValueKey(_count))),
            TextButton(onPressed: () {
              setState(() {
                _count += 1;
              });
            }, child: Text('Plus'))
          ],
        ),
      ),
    );
  }
}

 

일단 이 위젯을 사용하기 위해선 기본적으로 Stateful 인 상태여야 한다. 당연하게도 이 상태로 해놔야 애니메이션이 적용이 되니 말이다. 일단 나도 공식 예제를 따라서 만들어 보았는데 이게 젤 쉬운 느낌이 들어서 그랬다.

만든 것은 숫자가 바뀌면 간단한 Fade 애니메이션이 들어가는 거다.

먼저 사용할 int 변수를 하나 만들어주겠다.

int _count = 0;

 

이제 이걸로 텍스트에 표시하고 key 에 넣어줄 것이다.

AnimatedSwitcher(
  duration: Duration(milliseconds: 400),
    transitionBuilder: (child, animation) {
      return FadeTransition(opacity: animation, child: child,);
    },
    child: Text('$_count', key: ValueKey(_count))),

그 후에 바로 AnimatedSwitcher 를 사용했는데 조금씩 뜯어서 설명하겠다.

 

먼저 duration, 뭐 이건 모를 거라 생각하지 않는다. 자신이 원하는 실행 시간을 Duration 으로 조절해줄 수 있다.

duration: Duration(milliseconds: 400),

 

그다음은 빌더 함수인 transitionBuilder 이다.

transitionBuilder: (child, animation) {
  return FadeTransition(opacity: animation, child: child,);
},

빌더 함수인만큼 파라미터를 주는데 이거를 두 개 다 사용할 것이다.

일단 지금 나는 여기서 간단한 Fade애니메이션을 줄 수 있는 FadeTrandsition 을 주고 있다. 이 위젯은 아규먼트로 opacity 값을 받는데 여기다가 그냥 위에서 주는 aniamtion 파라미터 넣어주면 된다. 그런 후 직접 child 를 추가해서 child 파라미터를 넣어줘야 한다.

이렇게 넣어주는 이류를 짚고 가겠다.

transitionBuilder는 다음 두 인자를 받는다.

 

  • child: 전환 대상 새 위젯
  • animation: 0.0 ~ 1.0 사이로 변화하는 Animation<double>

이 두 개를 받아서 이렇게 만들었으니

FadeTransition(opacity: animation, child: child,);

 

animation 값이 0 -> 1로 증가하면서 child 위젯의 투명도(opacity)도 0 -> 1로 변화하게 된다. 이렇게 되면서 fade 효과가 나타는 것이다.

다시 말해 이 코드는 새로 보여줄 위젯(child)을 FadeTransition 안에 넣는 것이고, 이로 인해 AnimatedSwitcher 가 새 위젯으로 전환할 때 애니메이션을 적용하는 코드라는 것이다.

 

이제 중요하다. 이 AnimatedSwicher 위젯은 어쨌든 간에 위젯끼리 서로 전환하는 효과를 주는 위젯인데 어떠한 위젯끼리 전환되는지를 알 수 있어야 한다. 그래서 key 를 무조건 넣어줘야 한다.

child: Text('$_count', key: ValueKey(_count))),

 

그냥 count 변수를 표시하는 텍스트이지만 key 를 넣어서 고유한 번호를 부여해줬다. 이렇게 key 를 넣게 되면 count 값이 바뀔 때마다 새로운 key 가 텍스트에 부여되기 때문에 계속해서 애니메이션을 적용시켜 줄 수 있는 것이다.

밑에는 그냥 평범하게 버튼 누르면 count 값 올라게 만들었다.

TextButton(onPressed: () {
  setState(() {
    _count += 1;
  });
}, child: Text('Plus'))

 

이해가 안 됐을 이들을 위해 더 쉬운 예제도 준비해 놨다.

class _TestState extends State<Test> {
  bool _toggle = true;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: AnimatedSwitcher(
          duration: Duration(milliseconds: 500),
          transitionBuilder: (child, animation) => ScaleTransition(scale: animation, child: child),
          child: _toggle
              ? Container(
            key: ValueKey(1),
            width: 100,
            height: 100,
            color: Colors.blue,
          )
              : Container(
            key: ValueKey(2),
            width: 100,
            height: 100,
            color: Colors.red,
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => setState(() => _toggle = !_toggle),
        child: Icon(Icons.swap_horiz),
      ),
    );
  }
}

 

 

이 코드를 보면 이제 직관적으로 이해가 될 것이다.

 

암튼 이렇게 AnimatedSwitcher 에 대해서 알아보았다. 이번엔 진짜 간단하게 구성해 보았는데 도움이 되었으면 좋겠다. 그럼 마치겠다.

 

반응형