[Flutter] 애니메이션
플러터의 애니메이션에는 두 가지 종류가 있다.
1. Explicit
애니메이션의 시작, 중지, 방향 등 모든 부분을 개발자가 직접 제어한다.
Explicit 애니메이션은 일반적으로 시간에 따라 변하는 값이기 때문에 상태를 가지고 있다고 볼 수 있다.
따라서 Explicit 애니메이션을 구현하는 위젯은 대부분 StatefulWidget을 상속받는다.
class _CategoriesScreenState extends State<CategoriesScreen> with SingleTickerProviderStateMixin {
late AnimationController _animationController;
@override
void initState() {
_animationController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 300),
lowerBound: 0,
upperBound: 1,
);
_animationController.forward();
}
@override
void dispose() {
_animationController.dispose();
}
...
}
late 키워드는 나중에 초기화되는 변수를 선언할 때 사용된다.
future와 비슷한 역할을 하지만 사용하는 방식과 역할이 좀 다르다.
Future : 비동기 작업의 결과를 나타낼 때 사용한다.
late : non nullable 변수를 나중에 초기화한다.
AnimationController 객체를 State 클래스에서 생성하고 TickerProvider를 인수로 받는다.
(TickerProvider는 애니메이션 프레임 사이의 시간 차이를 나타낸다)
vsync : TickerProvider를 받아 애니메이션에게 프레임 간격에 따른 시간을 제공한다.
duration : 애니메이션 전체 길이를 알려준다.
lowerBound, upperBound : 애니메이션 값의 상한과 하한을 설정한다. (시작과 종료)
forward() 메서드로 애니메이션을 lowerBound에서 upperBound로 값을 변경시키고, duration에 지정된 값 동안 애니메이션을 실행한다.
위의 예시에서는 initState 메서드 내부에서 애니메이션을 시작한다.
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _animationController,
child: GridView(
padding: const EdgeInsets.all(24),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 3 / 2,
crossAxisSpacing: 20,
mainAxisSpacing: 20,
),
children: [
// availableCategories.map((category) => CategoryGridItem(category: category)).toList()
for (final category in availableCategories)
CategoryGridItem(
category: category,
onSelectCategory: () {
_selectCategory(context, category);
},
)
],
),
builder: (context, child) => Padding(
padding: EdgeInsets.only(
top: 100 - _animationController.value * 100,
),
child: child));
}
build 메서드의 반환값을 AnimatedBuilder 위젯으로 감싸서 애니메이션을 구현한다.
매번 상태 변경을 위해 setState 메서드를 호출하는 대신 애니메이션 값을 사용해 위젯을 다시 생성할 수 있다.
animation : _controller로 정의해 둔 애니메이션을 설정한다. 이 값이 빌더 함수에서 사용된다
child : 애니메이션과 무관한 부분은 한 번만 빌드하고 변화하는 부분만 빌드한다.
Explicit 애니메이션을 구현한다고 해도 플러터가 여러 가지 유용한 위젯들을 제공하니 필요에 따라 찾아서 사용하자.
TweenAnimationBuilder : 시작 값과 끝 값을 애니메이션으로 전환한다.
CurvedAnimation : 애니메이션에 곡선을 적용한다.
SlideTransition : 슬라이드를 적용할 때 사용한다.
...
2. Implicit
플러터가 애니메이션의 수명주기를 대신 관리해준다.
애니메이션의 시작, 종료만 지정해주면 플러터가 전체 애니메이션을 처리한다.
icon: AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
transitionBuilder: (child, animation) {
return RotationTransition(
turns: animation,
child: child,
);
},
child: Icon( isFavorite ? Icons.star : Icons.star_border, key: ValueKey(isFavorite)),
),
Implicit 애니메이션을 구현할 때는 플러터가 제공하는 위젯을 그대로 사용하면 된다.
AnimatedSwitcher, AnimatedContainer, AnimatedCrossFade 등 여러 가지 위젯을 제공하니 필요할 때 찾아보자.
예시에서는 두 개의 위젯 간 전환을 구현할 때 사용하는 AnimatedSwticher를 사용한다.
각 child에 대한 고유한 key를 통해 child를 구분하니 key를 설정해 줘야 한다.
duration : 애니메이션이 완료되는데 걸리는 시간을 지정한다.
transitionBuilder : 애니메이션 전환 효과를 정의한다.
두 개의 화면을 연결해서 애니메이션을 만들 때는 Hero 위젯을 사용한다.
Hero(
tag: ,
child: ...,
)
각 Hero 위젯에는 식별할 수 있는 태그가 필요하다.
두 화면에서 같은 tag를 가진 Hero 위젯을 선언해두면 두 화면 사이를 이동할 때 플러터가 부드러운 애니메이션 효과를 적용한다.
'Mobile > Flutter' 카테고리의 다른 글
[Flutter] Riverpod 상태 관리 (0) | 2023.06.24 |
---|---|
[Flutter] Theme와 세 가지 트리 (0) | 2023.06.19 |
[Flutter] 여러 가지 화면과 사용자 입력 관리 (0) | 2023.06.17 |
[Flutter] 위젯 렌더링과 다트 문법 (0) | 2023.06.16 |
[Flutter] Dart 언어와 StatefulWidget (0) | 2023.06.14 |
댓글
이 글 공유하기
다른 글
-
[Flutter] Riverpod 상태 관리
[Flutter] Riverpod 상태 관리
2023.06.24 -
[Flutter] Theme와 세 가지 트리
[Flutter] Theme와 세 가지 트리
2023.06.19 -
[Flutter] 여러 가지 화면과 사용자 입력 관리
[Flutter] 여러 가지 화면과 사용자 입력 관리
2023.06.17 -
[Flutter] 위젯 렌더링과 다트 문법
[Flutter] 위젯 렌더링과 다트 문법
2023.06.16