
Material Design의 Motion 패턴을 구현한 고품질 사전 제작 애니메이션 패키지
pub.dev: https://pub.dev/packages/animations
$ flutter pub add animations import 'package:animations/animations.dart';작은 요소에서 전체 화면으로 확장되는 애니메이션. Material Design 권장.
OpenContainer(
closedBuilder: (context, action) => Card(...),
openBuilder: (context, action) => DetailPage(),
)탭이나 페이지 전환 시 좌우 슬라이드. 부드러운 전환.
PageTransitionSwitcher(
transitionBuilder: (child, animation, secondary) =>
SharedAxisTransition(
animation: animation,
secondaryAnimation: secondary,
transitionType: SharedAxisTransitionType.horizontal,
child: child,
),
child: _pages[_index],
)하단 네비게이션 전환에 최적. 페이드 인/아웃 효과.
PageTransitionSwitcher(
transitionBuilder: (child, animation, secondary) =>
FadeThroughTransition(
animation: animation,
secondaryAnimation: secondary,
child: child,
),
child: _pages[_selectedIndex],
)검색 아이콘에서 전체 화면 검색으로 자연스럽게 전환.
OpenContainer(
closedShape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24),
),
closedBuilder: (context, action) =>
Container(child: Icon(Icons.search)),
openBuilder: (context, action) => SearchPage(),
)위아래 슬라이드 전환. 계층 구조 표현에 적합.
PageTransitionSwitcher(
transitionBuilder: (child, animation, secondary) =>
SharedAxisTransition(
animation: animation,
secondaryAnimation: secondary,
transitionType: SharedAxisTransitionType.vertical,
child: child,
),
child: _currentPage,
)확대/축소 전환. 관련성 표현에 효과적.
PageTransitionSwitcher(
transitionBuilder: (child, animation, secondary) =>
SharedAxisTransition(
animation: animation,
secondaryAnimation: secondary,
transitionType: SharedAxisTransitionType.scaled,
child: child,
),
child: _detailPage,
)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,
);
},
),
);여러 단계를 순차적으로 연결하여 복잡한 애니메이션 생성.
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);Material Motion과 Hero 애니메이션 결합.
// 첫 번째 화면
OpenContainer(
closedBuilder: (context, action) =>
Hero(
tag: 'product-${id}',
child: ProductCard(),
),
openBuilder: (context, action) =>
Hero(
tag: 'product-${id}',
child: ProductDetail(),
),
)애니메이션 성능 최적화 기법. 낮은 사양에서도 60fps 유지.
// ✅ RepaintBoundary로 불필요한 리페인트 방지
RepaintBoundary(
child: OpenContainer(
closedBuilder: (context, action) => ClosedWidget(),
openBuilder: (context, action) => OpenWidget(),
),
)
// ✅ 애니메이션 시간 조절
OpenContainer(
transitionDuration: Duration(milliseconds: 300),
// 기본 300ms가 적절
)리스트 아이템에서 상세 페이지로 자연스러운 확장.
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),
);
},
)하단 네비게이션 탭 전환 시 부드러운 애니메이션.
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),
)Modal bottom sheet를 Material Motion으로 표시.
void _showModal() {
showModal(
context: context,
builder: (context) => Container(
height: 400,
child: Column(
children: [
// 모달 내용
],
),
),
// Fade Through 전환 사용
configuration: FadeScaleTransitionConfiguration(),
);
}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