Flutter Pub Collection
[ Animations ]
Flutter 패키지

소개

Material Design의 Motion 패턴을 구현한 고품질 사전 제작 애니메이션 패키지

설치

pub.dev: https://pub.dev/packages/animations

$ flutter pub add animations
import 'package:animations/animations.dart';

1. Container Transform

작은 요소에서 전체 화면으로 확장되는 애니메이션. Material Design 권장.

OpenContainer(
  closedBuilder: (context, action) => Card(...),
  openBuilder: (context, action) => DetailPage(),
)

2. Shared Axis (Horizontal)

탭이나 페이지 전환 시 좌우 슬라이드. 부드러운 전환.

PageTransitionSwitcher(
  transitionBuilder: (child, animation, secondary) =>
    SharedAxisTransition(
      animation: animation,
      secondaryAnimation: secondary,
      transitionType: SharedAxisTransitionType.horizontal,
      child: child,
    ),
  child: _pages[_index],
)

3. Fade Through

하단 네비게이션 전환에 최적. 페이드 인/아웃 효과.

PageTransitionSwitcher(
  transitionBuilder: (child, animation, secondary) =>
    FadeThroughTransition(
      animation: animation,
      secondaryAnimation: secondary,
      child: child,
    ),
  child: _pages[_selectedIndex],
)

4. 실전 예제: 검색창 확장

검색 아이콘에서 전체 화면 검색으로 자연스럽게 전환.

OpenContainer(
  closedShape: RoundedRectangleBorder(
    borderRadius: BorderRadius.circular(24),
  ),
  closedBuilder: (context, action) =>
    Container(child: Icon(Icons.search)),
  openBuilder: (context, action) => SearchPage(),
)

5. Shared Axis (Vertical)

위아래 슬라이드 전환. 계층 구조 표현에 적합.

PageTransitionSwitcher(
  transitionBuilder: (child, animation, secondary) =>
    SharedAxisTransition(
      animation: animation,
      secondaryAnimation: secondary,
      transitionType: SharedAxisTransitionType.vertical,
      child: child,
    ),
  child: _currentPage,
)

6. Shared Axis (Scaled)

확대/축소 전환. 관련성 표현에 효과적.

PageTransitionSwitcher(
  transitionBuilder: (child, animation, secondary) =>
    SharedAxisTransition(
      animation: animation,
      secondaryAnimation: secondary,
      transitionType: SharedAxisTransitionType.scaled,
      child: child,
    ),
  child: _detailPage,
)

7. 커스텀 전환 애니메이션

PageRouteBuilder로 커스텀 페이지 전환 구현.

Navigator.push(
  context,
  PageRouteBuilder(
    pageBuilder: (context, animation, secondaryAnimation) =>
      NextPage(),
    transitionsBuilder: (context, animation, secondaryAnimation, child) {
      const begin = Offset(1.0, 0.0);
      const end = Offset.zero;
      const curve = Curves.easeInOut;

      var tween = Tween(begin: begin, end: end)
        .chain(CurveTween(curve: curve));

      return SlideTransition(
        position: animation.drive(tween),
        child: child,
      );
    },
  ),
);

8. TweenSequence로 복잡한 애니메이션

여러 단계를 순차적으로 연결하여 복잡한 애니메이션 생성.

final animation = TweenSequence<double>([
  TweenSequenceItem(
    tween: Tween<double>(begin: 0.0, end: 1.0)
      .chain(CurveTween(curve: Curves.easeIn)),
    weight: 40.0,
  ),
  TweenSequenceItem(
    tween: ConstantTween<double>(1.0),
    weight: 20.0,
  ),
  TweenSequenceItem(
    tween: Tween<double>(begin: 1.0, end: 0.0)
      .chain(CurveTween(curve: Curves.easeOut)),
    weight: 40.0,
  ),
]).animate(_controller);

9. Hero 애니메이션 통합

Material Motion과 Hero 애니메이션 결합.

// 첫 번째 화면
OpenContainer(
  closedBuilder: (context, action) =>
    Hero(
      tag: 'product-${id}',
      child: ProductCard(),
    ),
  openBuilder: (context, action) =>
    Hero(
      tag: 'product-${id}',
      child: ProductDetail(),
    ),
)

10. 성능 최적화

애니메이션 성능 최적화 기법. 낮은 사양에서도 60fps 유지.

// ✅ RepaintBoundary로 불필요한 리페인트 방지
RepaintBoundary(
  child: OpenContainer(
    closedBuilder: (context, action) => ClosedWidget(),
    openBuilder: (context, action) => OpenWidget(),
  ),
)

// ✅ 애니메이션 시간 조절
OpenContainer(
  transitionDuration: Duration(milliseconds: 300),
  // 기본 300ms가 적절
)

11. 실전 예제: 상세 페이지 전환

리스트 아이템에서 상세 페이지로 자연스러운 확장.

ListView.builder(
  itemBuilder: (context, index) {
    return OpenContainer(
      transitionType: ContainerTransitionType.fade,
      closedBuilder: (context, action) =>
        ListTile(
          title: Text('Item $index'),
          leading: CircleAvatar(),
        ),
      openBuilder: (context, action) =>
        DetailPage(index: index),
    );
  },
)

12. 실전 예제: 탭 전환

하단 네비게이션 탭 전환 시 부드러운 애니메이션.

int _currentIndex = 0;

PageTransitionSwitcher(
  duration: const Duration(milliseconds: 300),
  transitionBuilder: (child, animation, secondary) =>
    FadeThroughTransition(
      animation: animation,
      secondaryAnimation: secondary,
      child: child,
    ),
  child: _pages[_currentIndex],
)

// BottomNavigationBar
BottomNavigationBar(
  currentIndex: _currentIndex,
  onTap: (index) => setState(() => _currentIndex = index),
)

13. 실전 예제: 모달 표시

Modal bottom sheet를 Material Motion으로 표시.

void _showModal() {
  showModal(
    context: context,
    builder: (context) => Container(
      height: 400,
      child: Column(
        children: [
          // 모달 내용
        ],
      ),
    ),
    // Fade Through 전환 사용
    configuration: FadeScaleTransitionConfiguration(),
  );
}

14. 주의사항

Material Motion 애니메이션 사용 시 핵심 가이드.

// ✅ 적절한 전환 타입 선택
// Container Transform: 리스트 → 상세
// Shared Axis: 탭, 페이지 전환
// Fade Through: 하단 네비게이션

// ✅ 애니메이션 시간 일관성
const standardDuration = Duration(milliseconds: 300);

// ✅ RepaintBoundary 사용
RepaintBoundary(child: AnimatedWidget())

// ✅ 과도한 애니메이션 중첩 피하기
// 한 번에 하나의 주요 애니메이션

// ❌ 너무 긴 애니메이션 (500ms 이상) 피하기
// ❌ 복잡한 위젯에서 60fps 미달 시 최적화 필요

패키지 정보

pub.dev: https://pub.dev/packages/animations

version: 2.1.0

likes: 6.6k

Publisher: flutter.dev