[flutter] 스크롤 애니메이션을 위한 클리퍼 애니메이션 구현 방법

컨텐츠 스크롤 중에 발생하는 애니메이션은 앱에 동적인 요소를 추가하여 사용자 경험을 향상시킬 수 있는 좋은 방법입니다. 이번 포스트에서는 Flutter에서 스크롤 애니메이션을 구현하기 위해 클리퍼 (Clipper) 애니메이션을 사용하는 방법을 알아보겠습니다.

클리퍼 (Clipper)란?

클리퍼는 특정 모양으로 컨테이너를 자르는 역할을 합니다. Flutter에서 클리퍼는 CustomClipper 클래스를 상속하여 구현됩니다. 스크롤 애니메이션을 위해 사용할 클리퍼 애니메이션을 만들기 위해 CustomClipper 클래스를 확장하여 사용자 정의 클리퍼를 작성합니다.

클리퍼 애니메이션 구현 방법

먼저, 스크롤 애니메이션을 적용할 위젯을 생성합니다. 일반적으로 스크롤 가능한 ListViewCustomScrollView를 사용합니다. 아래는 ListView 위젯을 사용하는 예시입니다.

import 'package:flutter/material.dart';

class ScrollAnimationWidget extends StatefulWidget {
  @override
  _ScrollAnimationWidgetState createState() => _ScrollAnimationWidgetState();
}

class _ScrollAnimationWidgetState extends State<ScrollAnimationWidget> {
  double _clipPercentage = 0.0;

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: 100,
      itemBuilder: (context, index) {
        return ClipPath(
          clipper: CustomClipperClass(_clipPercentage),
          child: Container(
            height: 100,
            color: Colors.blue,
          ),
        );
      },
    );
  }
}

위 코드에서 _clipPercentage 변수는 클리퍼 애니메이션의 적용 정도를 제어하기 위한 변수입니다. 이 값은 스크롤 위치에 따라 변화하게 됩니다.

다음으로 사용자 정의 클리퍼를 작성합니다. 해당 클리퍼 클래스는 CustomClipper 클래스를 상속받고 getClip() 메서드를 오버라이드하여 클리핑 모양을 정의합니다.

class CustomClipperClass extends CustomClipper<Path> {
  final double clipPercentage;

  CustomClipperClass(this.clipPercentage);

  @override
  Path getClip(Size size) {
    final path = Path();
    final height = size.height * clipPercentage;

    path.moveTo(0, 0);
    path.lineTo(0, size.height - height);
    path.lineTo(size.width, size.height);
    path.lineTo(size.width, 0);
    path.close();

    return path;
  }

  @override
  bool shouldReclip(CustomClipper<Path> oldClipper) => true;
}

위 코드에서 getClip() 메서드에서 Path를 이용하여 클리핑 모양을 정의합니다. shouldReclip() 메서드는 클리퍼가 변경될 때마다 클리핑을 다시 수행해야 하는지를 판단하는 로직을 정의합니다. 여기서는 항상 true를 반환하도록 설정하여 스크롤 애니메이션을 지속적으로 업데이트 할 수 있도록 합니다.

마지막으로, 앱에서 위젯을 사용하여 클리퍼 애니메이션을 적용합니다. 이를 위해 스크롤 이벤트를 감지하고 _clipPercentage 변수 값을 갱신하는 로직을 구현해야 합니다.

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: NotificationListener<ScrollNotification>(
          onNotification: (scrollNotification) {
            if (scrollNotification is ScrollUpdateNotification) {
              final scrollOffset = scrollNotification.metrics.pixels;
              final screenHeight = MediaQuery.of(context).size.height;
              final scrollPercentage = scrollOffset / screenHeight;

              setState(() {
                _clipPercentage = scrollPercentage;
              });
            }
            return true;
          },
          child: ScrollAnimationWidget(),
        ),
      ),
    );
  }
}

위 코드에서 NotificationListener를 사용하여 스크롤 이벤트를 감지하고 _clipPercentage 변수 값을 갱신합니다. 이 값을 이용하여 클리퍼 애니메이션을 적용할 수 있습니다.

이제 위 소스 코드를 참고하여 스크롤 애니메이션을 적용한 클리퍼 애니메이션을 구현할 수 있습니다.

참고 자료