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

Flutter[플러터] / AnimatedCrossFade 를 사용하여 페이드 효과 넣기 (전환, 패이드, 서서히, fade in, fade out, 애니메이션, 크로스 페이드) AnimatedCrossFade (Flutter Widget of the Week)

by ch5c 2025. 6. 16.
반응형

AnimatedCrossFade class

두 개의 주어진 자식 요소 사이를 크로스 페이드하고, 두 요소의 크기 사이에서 애니메이션을 적용하는 위젯입니다.

애니메이션은 crossFadeState 매개변수를 통해 제어됩니다. firstCurve 와 secondCurve는 두 자식 요소의 불투명도 곡선을 나타냅니다. firstCurve 는 반전되어 Curves.linear 처럼 점점 커지는 곡선을 제공할 때 페이드 아웃됩니다. sizeCurve 는 페이드 아웃하는 자식 요소의 크기와 페이드 인하는 자식 요소의 크기 사이에서 애니메이션을 적용하는 데 사용되는 곡선입니다.

이 위젯은 너비가 같은 두 위젯을 페이드 처리하는 데 사용됩니다. 두 자식 위젯의 높이가 다른 경우, 애니메이션이 실행되는 동안 위젯의 위쪽 가장자리를 정렬하여 위젯이 넘치는 부분을 잘라냅니다. 즉, 아래쪽이 잘립니다.

기존 AnimatedCrossFade가 crossFadeState 속성에 다른 값으로 다시 빌드되면 애니메이션이 자동으로 트리거 됩니다.

https://youtu.be/PGK2UUAyE54

공식 문서 코드

 

 


흔히 영상 매체에서는 화면에서 화면을 넘어갈 때 여러 효과를 줘서 자연스럽게 화면 전환을 하곤 한다. 특히 이 화면 전환을 할 때 가장 많이 사용되는 것을 뽑으라고 한다면 fade-in/fade-out 일 것이다. 근데 이 페이드 효과를 앱에 넣고 싶을 수 있다. 이럴 때에는 무슨 위젯을 써야 할까? FadeTranstion? 물론 좋은 선택이다. 하지만 더욱 쉽고 빠르고 범용성 있게 페이드 전환 효과를 구현해 놓은 위젯이 있는데 바로 AnimatedCrossFade 위젯이다.

이 AnimatedCrossFade 위젯은 두 개의 위젯 사이를 부드럽게 전환하는 데 사용되는 위젯이다. 이 위젯은 fade-in/fade-out 애니메이션을 통해 첫 번째 위젯과 두 번째 위젯 사이를 전환시킨다. 바로 한번 알아보자.

하위 속성
속성명 타입 기본값 설명
firstChild Widget 처음에 표시되는 위젯
secondChild Widget 전환 후 표시되는 위젯
crossFadeState CrossFadeState 현재 어떤 위젯을 보여줄지 결정하는 상태값
duration Duration 애니메이션의 전체 지속 시간
reverseDuration Duration? null 역방향 애니메이션 시간
firstCurve Curve Curves.linear 첫 번째 위젯의 페이드 아웃 커브
secondCurve Curve Curves.linear 두 번째 위젯의 페이드 인 커브
sizeCurve Curve Curves.linear 위젯 사이즈 전환 시 사용되는 커브
alignment AlignmentGeometry Alignment.topCenter 위젯 전환 시 정렬 방식
layoutBuilder AnimatedCrossFadeBuilder defaultLayoutBuilder 위젯의 배치 방식을 정의하는 빌더
excludeBottomFocus bool true 하단 위젯이 포커스를 받지 않도록 설정

사용하는 방법은 정말 간단한데 지속 시간과 전환시킬 위젯 두 개, 마지막으로 전환 시 보여줄 위젯 이렇게 4가지 정도만 적으면 끝난다.

(전체 코드)

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> {
  bool _first = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            AnimatedCrossFade(
              duration: Duration(seconds: 2),
              firstChild: Container(width: 100, height: 100, color: Colors.red,),
              secondChild: Container(width: 100, height: 100, color: Colors.blue,),
              crossFadeState: _first ? CrossFadeState.showFirst : CrossFadeState.showSecond,
            ),
            TextButton(
              onPressed: () {
                setState(() {
                  _first = !_first;
                });
              },
              child: Text('Click to change!'),
            ),
          ],
        ),
      ),
    );
  }
}

기본적으로 전환을 위한 bool 타입 변수를 하나 만들어주는 것을 권장한다. 권장할 뿐 필수는 아니다.

위 코드에서는 간단하게 값이 바뀔 때 페이드 전환 효과가 나타나는 것을 보여주고 있다.

AnimatedCrossFade(
  duration: Duration(seconds: 2),
  firstChild: Container(width: 100, height: 100, color: Colors.red,),
  secondChild: Container(width: 100, height: 100, color: Colors.blue,),
  crossFadeState: _first ? CrossFadeState.showFirst : CrossFadeState.showSecond,
),

지금 이 코드는 각기 다른 컨테이너를 전환시키는 코드이다.

지금 보면 firstChild 와 secondChild 란 속성이 있다. 여기에는 우리가 전환시킬 위젯을 넣어주면 되는데 영상 편집 프로그램을 생각하면 된다. 일단 페이드를 시키려면 페이드를 시켜줄 화면이 두 개 필요하기 때문에 그거 넣어주면 되는 것이다.

이제 그 후 crossFadeState 에 그냥 삼항 연산자로 firstChild 보여줄 거냐 secondChild 보여줄 거냐 골라주면 된다.

여기서 crossFadeState 는 CrossFadeState 를 타입으로 가지기 때문에 이 타입에서 접근해서 가져와주면 된다.

CrossFadeState.showFirst // firstChild 에 접근
CrossFadeState.showSecond // secondChild 에 접근

 

솔직히 이것만으로 이미 거의 끝났지만 만약 사이즈가 다른 위젯을 전환시켜야 한다면 어떻게 할까? 물론 다른 크기여도 가동은 매우 잘할 것이다. 하지만 제한되지 않은 크기의 두 위젯 사이에서 크로스 페이드를 한다면 페이드 효과만 먹여주는 게 아니라 알아서 맞는 효과(사이즈)를 먹여주게 된다. 이제 여기서 위젯이 특정한 크기를 갖고 있다면 맞춤형 layoutBuilder 를 이용하여 갑작스러운 위젯의 이동을 피할 수 있게 된다.

AnimatedCrossFade(
  layoutBuilder: (topChild, topChildKey, bottomChild, bottomChildKey) {
    return Stack(
      clipBehavior: Clip.none,
      alignment: Alignment.center,
      children: [
        Positioned(
          key: bottomChildKey,
          top: 0,
          child: bottomChild,
        ),
        Positioned(
          key: topChildKey,
          child: topChild,
        ),
      ],
    );
  },
  duration: Duration(seconds: 2),
  firstChild: Container(width: 100, height: 100, color: Colors.red,),
  secondChild: Container(width: 100, height: 200, color: Colors.blue,),
  crossFadeState: _first ? CrossFadeState.showFirst : CrossFadeState.showSecond,
),

현재 layoutBuilder 의 코드는 공식 코드를 그대로 가져 온것인데 layoutBuilder 의 인자를 보면 탑이랑 바텀의 자식값을 주고 키값을 주고 있다. 여기서 탑이랑 바텀은 물리적인 것이 아니고 순서라고 생각하면 편하다. 암튼 거기다가 똑같이 키값 넣어주면 되겠는데 눈치챘는지 모르겠지만 밑에 적은 firstChild, secondChild 와 연동되고 layoutBuilder 안에서 세부적으로 조절할 수 있는 것이다.

 

 

이렇게 페이드뿐만 아니라 직접적인 크기 조절도 가능하게 해주는 것이 이 AnimatedCrossFade 위젯이다. 이 위젯은 위젯 간의 자연스러운 전환을 추구하고 코드 작성이 귀찮다면 꼭 사용해봐야 하는 위젯이 되겠다. 암튼 도움이 되었길 바라며 마치겠다.

반응형

 

반응형