플러터(Flutter)의 애니메이션은 두 가지 방법이 존재합니다.
- 명시적(Explict) 애니메이션
- 암시적(Implict) 애니메이션
둘의 차이점은 다음과 같습니다.
플러터의 명시적(Explict) 애니메이션
플러터에서 명시적 애니메이션은 AnimationController를 사용하여 정의합니다.
AnimationController는 애니메이션의 수명 주기의 시작, 정지, 반전 등을 제어하는데 사용됩니다.
그렇기 때문에 명시적 애니메이션이 커스텀할 수 있는 범위가 높고 할 수 있는게 많습니다.
그리고 StatefulWidget에서만 사용할 수 있다는 특징을 갖고 있습니다.
플러터의 암시적(Implict) 애니메이션
애니메이션의 이미 지정되어 있는 플러터 프레임워크가 내부적으로 애니메이션을 처리합니다.
그렇기 때문에 간단하게 애니메이션을 만들 수 있다는 특징을 갖고 있습니다.
플러터에서 테스트 코드와
튜토리얼도 제공하고 있습니다.
플러터로 명시적(Explict) 애니메이션 만들기
먼저 애니메이션을 넣으려고 하는 UI가 StatelessWidget이라면 StatefulWidget으로 변경할 필요가 있습니다.
그 이후 with을 사용하여 TickerProviderStateMixin을 Mixin할 필요가 있습니다.
만약 하나의 AnimationController만 사용할 예정이라면 SingleTickerProviderStateMixin을 Mixin 해야 합니다.
예를 들면 다음과 같은 코드가 되어야 합니다.
class CategoriesScreen extends StatefulWidget {
const CategoriesScreen({super.key, required this.availableMeals});
~~~
@override
State<CategoriesScreen> createState() => _CategoriesScreenState();
}
// 다음과 같이 with을 사용하여 SingleTickerProviderStateMixin을 Mixin 한다.
class _CategoriesScreenState extends State<CategoriesScreen> with SingleTickerProviderStateMixin {
@override
Widget build(BuildContext context) {
~~~
}
}
그 이후 다음과 같이 AnimationController를 초기화합니다.
class _CategoriesScreenState extends State<CategoriesScreen> with SingleTickerProviderStateMixin {
// late로 AnimationController 객체를 만든다.
late AnimationController _animationController;
@override
void initState() {
super.initState();
// vsync는 이 애니메이션이 모든 프레임에서 실행되도록 하는 매개변수임('티커'라고 불린다)
// lowerBound, upperBound는 각각 애니메이션의 시작과 끝을 의미한다.
_animationController =
AnimationController(vsync: this, duration: const Duration(milliseconds: 300), lowerBound: 0, upperBound: 1);
}
~~~~
}
그리고 마지막으로 애니메이션을 사용하지 않을 때는 dispose를 사용하여 객체를 비워줍니다.
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
AnimatedBuilder를 사용해서 AnimationController 적용하기
기존에 있던 build() 함수에 AnimatedBuilder를 사용해서 위에서 정의한 AnimationController를 사용할 수 있습니다.
다음과 같이 AnimatedBuiler를 정의합니다.
@override
Widget build(BuildContext context) {
// child: 애니메이션을 재생해도 변화하지 않는 부분(= 기존의 UI 부분)
return AnimatedBuilder(
animation: _animationController,
child: GridView(
padding: const EdgeInsets.all(16),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 3 / 2,
crossAxisSpacing: 20,
mainAxisSpacing: 20,
),
children: [
for (final category in availableCategories)
CategoryGridItem(
category: category,
onSelectCategory: () {
_selectCategory(context, category);
},
)
],
),
// AnimatedBuilder에 전달되는 함수로, 애니메이션이 변화할 때마다 호출되어 위젯을 다시 빌
builder: (context, child) => Padding(
padding: EdgeInsets.only(
top: 100 - _animationController.value * 100,
),
child: child),
);
}
이제 initState() 함수에서 처음 화면을 생성할 때 지금까지 정의한 애니메이션을 실행하게 한다.
@override
void initState() {
super.initState();
// vsync는 이 애니메이션이 모든 프레임에서 실행되도록 하는 매개변수임
_animationController =
AnimationController(vsync: this, duration: const Duration(milliseconds: 300), lowerBound: 0, upperBound: 1);
// 애니메이션 실행
_animationController.forward();
}
실행 결과
위 코드를 실행하면 다음과 같이 화면이 생성되었을 때 UI 요소가 밑에서 위로 올라오는 애니메이션을 갖게 된다.
다음 포스팅에서는 암시적 애니메이션을 만드는 방법과
위에서 만든 명시적 애니메이션을 좀 더 수정하는 방법에 대해 알아보겠습니다.
'플러터(flutter)' 카테고리의 다른 글
플러터에서 Rest API로 Firebase Realtime Database 사용하기 (1) | 2023.12.23 |
---|---|
플러터의 AnimatedBuilder를 사용하여 Animation 만들기 - 2 (0) | 2023.12.20 |
플러터의 Riverpod 사용 방법 기초부터 자세히 설명 - 2 (0) | 2023.12.07 |
플러터의 Riverpod 사용 방법 기초부터 자세히 설명 - 1 (2) | 2023.12.06 |
플러터(Flutter)에서 Widget UI에 있는 Key란 무엇인가? (0) | 2023.09.25 |
"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."
댓글