일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- Maui
- MSSQL
- 플러터
- AnimationController
- db
- Binding
- 오류
- 깃허브
- GitHub
- 자바스크립트
- Firebase
- 바인딩
- 닷넷
- 파이어베이스
- HTML
- Flutter
- Animation
- MS-SQL
- JavaScript
- page
- .NET
- React JS
- 마우이
- listview
- 함수
- spring boot
- typescript
- 애니메이션
- MVVM
- 리엑트
- Today
- Total
개발노트
71. [Flutter] flutter_animate 패키지로 손쉽게 애니메이션 효과 주기 본문
flutter_animate
flutter_animate 패키지는 Flutter 애플리케이션에서 애니메이션을 쉽게 적용할 수 있도록 도와주는 패키지입니다. 이 패키지는 다양한 애니메이션 효과를 제공하며, 간편한 구문을 사용하여 애니메이션을 구현할 수 있습니다.
flutter_animate 패키지의 주요 특징은 다음과 같습니다:
- 다양한 애니메이션 효과: 패키지는 여러 가지 애니메이션 효과를 제공합니다. 이 효과들은 Fade, Scale, Rotate, Flip 등의 기본적인 애니메이션부터 Pulse, Shake, Wiggle과 같은 고급 애니메이션까지 다양합니다.
- 간편한 구문: 애니메이션을 구현할 때 간편한 구문을 제공하여 개발자가 복잡한 애니메이션 코드를 작성하지 않아도 되도록 합니다. 이로써 애니메이션 적용이 더욱 쉬워집니다.
- 메서드 체이닝 지원: 패키지는 메서드 체이닝을 지원하여 여러 애니메이션을 연속적으로 적용할 수 있도록 합니다. 이로써 여러 애니메이션을 간단하게 조합할 수 있습니다.
- 시간 지연 및 커브 제어: 애니메이션의 시작 시간을 지연시키고, 커브를 조정하여 애니메이션의 움직임을 더욱 자연스럽게 만들 수 있습니다.
flutter_animate 패키지를 사용하면 Flutter 애플리케이션에서 다양한 애니메이션을 쉽게 추가할 수 있으며, 사용자 경험을 향상시키는 데 도움이 됩니다.
- flutter_animate 설치링크: https://pub.dev/packages/flutter_animate
아래 부터 flutter_animate를 사용하는 3가지 방식을 나눠서 설명드리겠습니다.
1. AnimateList [] 를 사용하는 방식
*AnimateList는 List형태로, onInit, onPlay, onComplete와 같은 콜백 함수를 통해 Controller를 다루고 effects: 속성에 있는 애니메이션을 호출합니다.
- onInit: 애니메이션 리스트가 초기화될 때 호출되는 콜백 함수입니다. 여기서는 컨트롤러를 초기화하거나 다른 초기 설정을 수행할 수 있습니다. 여기서는 아무 동작도 하지 않습니다.
- onPlay: 애니메이션 재생이 시작될 때 호출되는 콜백 함수입니다. 애니메이션이 시작되면 이 콜백에서 원하는 작업을 수행할 수 있습니다. 여기서는 아무 동작도 하지 않습니다.
- onComplete: 애니메이션이 완료될 때 호출되는 콜백 함수입니다. 여기서는 애니메이션을 역방향으로 재생하도록 컨트롤러에 지시합니다.
- effects: 적용할 애니메이션 효과의 리스트입니다. 여기서는 **FlipEffect**와 ScaleEffect 두 가지 효과를 사용하고 있습니다. **FlipEffect**는 카드를 수직으로 뒤집는 효과를 주고, **ScaleEffect**는 크기를 조정하는 효과를 주는 것으로 보입니다.
- interval: 각 애니메이션 간의 지연 시간입니다. 여기서는 500밀리초로 설정되어 있습니다.
- children: 각 항목에 대한 위젯 리스트입니다. 여기서는 **colorList**의 각 색상에 대해 **Container**를 만들어 표시하고 있습니다. 각 **Container**는 정해진 색상과 모양을 가지고 있습니다.
*AnimateList가 List형이기 때문에 Column []의 children: 에 대괄호 없이 바로 AnimateList를 연결해주면됩니다.
AinmateList [] 사용 예시 소스.
import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
class TestScreen extends StatefulWidget {
static String routeName = "testscreen";
static String routeURL = "testscreen";
const TestScreen({super.key});
@override
State<TestScreen> createState() => _TestScreenState();
}
class _TestScreenState extends State<TestScreen> {
final List<MaterialColor> colorList = [
Colors.red,
Colors.orange,
Colors.yellow,
Colors.lightGreen,
Colors.lightBlue,
Colors.indigo,
Colors.deepPurple,
];
@override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Column(
children: AnimateList(
onInit: (controller) {},
onPlay: (controller) {},
onComplete: (controller) {
controller.reverse();
},
effects: [
const FlipEffect(
begin: 0,
end: 1,
direction: Axis.vertical,
duration: Duration(milliseconds: 500)),
const ScaleEffect(
begin: Offset(1, 1), end: Offset(1.5, 1.5))
],
interval: 500.ms,
children: [
for (int i = 0; i < colorList.length; i++)
Padding(
padding: const EdgeInsets.all(10),
child: Container(
height: 70,
width: 350,
decoration: BoxDecoration(
color: colorList[i],
borderRadius: const BorderRadius.all(
Radius.circular(25))),
),
),
]),
)
],
),
),
),
);
}
}
2. Animate() 를 사용하는 방식
*Animate() 은 target: 의 상태를 감시하며, 이에 따라 effects: [] 속성에 List에 있는 애니메이션 효과가 진행됩니다.
- target: 애니메이션의 대상값을 지정합니다. 여기서는 **_toggle**의 상태에 따라 0 또는 1의 값을 가집니다. 이 값이 변할 때마다 애니메이션도 갱신됩니다.
- effects: 적용할 애니메이션 효과의 리스트입니다. 여기서는 각 항목에 대해 **FlipEffect**와 ScaleEffect 두 가지 효과를 적용하고 있습니다. **FlipEffect**는 해당 위젯을 뒤집는 효과를 주고, **ScaleEffect**는 해당 위젯의 크기를 조정하는 효과를 줍니다. 각 효과에는 delay 속성이 있어서 각 항목에 애니메이션을 적용하는 시간을 조절할 수 있습니다.
- child: 각 애니메이션 효과가 적용될 위젯입니다. 여기서는 **Padding**을 통해 각 컨테이너를 감싸고 있습니다. 이렇게 함으로써 컨테이너 사이의 여백을 추가할 수 있습니다. **Container**는 리스트의 각 항목을 나타내며, **colorList**의 각 색상을 가지고 있습니다. 모든 컨테이너는 동일한 크기와 모양을 가지며, 각각의 색상을 가집니다.
Animate() 사용 예시 소스.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
class TestScreen extends StatefulWidget {
static String routeName = "testscreen";
static String routeURL = "testscreen";
const TestScreen({super.key});
@override
State<TestScreen> createState() => _TestScreenState();
}
class _TestScreenState extends State<TestScreen> {
bool _toggle = false;
final List<MaterialColor> colorList = [
Colors.red,
Colors.orange,
Colors.yellow,
Colors.lightGreen,
Colors.lightBlue,
Colors.indigo,
Colors.deepPurple,
];
void _onPressed() {
setState(() {
_toggle = !_toggle;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
CupertinoButton(
onPressed: _onPressed, child: const Text("Card Flip")),
for (int i = 0; i < colorList.length; i++)
Animate(
target: _toggle ? 0 : 1,
effects: [
FlipEffect(
begin: 0,
end: 1,
delay: Duration(milliseconds: 200 * i),
curve: Curves.fastOutSlowIn),
ScaleEffect(
begin: const Offset(1, 1),
end: const Offset(2, 1.5),
delay: Duration(milliseconds: 200 * i),
curve: Curves.bounceOut),
],
child: Padding(
padding: const EdgeInsets.all(10),
child: Container(
height: 70,
width: 350,
decoration: BoxDecoration(
color: colorList[i],
borderRadius:
const BorderRadius.all(Radius.circular(25))),
),
),
),
],
),
),
),
);
}
}
Animate()의 effects: 속성 리스트 예시
3. Widget 뒤에 .animate() 를 붙이는 방식 (*메서드 체이닝)
*[메서드 체이닝] 에 대해서는 아래에서 설명드리겠습니다.
위의 코드는 flutter_animate 패키지에서 제공하는 애니메이션 메서드 체이닝 기능을 사용하여 컨테이너에 여러 애니메이션 효과를 적용하는 부분입니다. 아래는 각 메서드와 속성에 대한 설명입니다.
- animate: 애니메이션을 적용할 위젯을 선택합니다. 여기서는 Container 위젯을 선택합니다.
- flipV: 수직 방향으로 뒤집는 애니메이션 효과를 추가합니다. **begin**과 **end**는 애니메이션의 시작과 끝 값을 나타냅니다. **curve**는 애니메이션의 변화를 제어하는 곡선을 나타냅니다. **delay**는 애니메이션 시작을 지연시키는 데 사용됩니다. 여기서는 FastOutSlowIn 곡선과 200 * i 밀리초의 지연을 사용합니다.
- then: 이전 애니메이션 후에 다음 애니메이션을 적용하기 위한 지연 시간을 추가합니다. 여기서는 1000밀리초의 지연을 추가했습니다.
- scale: 크기 조정 애니메이션 효과를 추가합니다. **begin**과 **end**는 애니메이션의 시작과 끝 값을 나타냅니다. **curve**는 애니메이션의 변화를 제어하는 곡선을 나타냅니다. **delay**는 애니메이션 시작을 지연시키는 데 사용됩니다. 여기서는 BounceOut 곡선과 200 * i 밀리초의 지연을 사용합니다.
Widget.animate() 사용 예시
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
class TestScreen extends StatefulWidget {
static String routeName = "testscreen";
static String routeURL = "testscreen";
const TestScreen({super.key});
@override
State<TestScreen> createState() => _TestScreenState();
}
class _TestScreenState extends State<TestScreen> {
bool _toggle = false;
final List<MaterialColor> colorList = [
Colors.red,
Colors.orange,
Colors.yellow,
Colors.lightGreen,
Colors.lightBlue,
Colors.indigo,
Colors.deepPurple,
];
void _onPressed() {
setState(() {
_toggle = !_toggle;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
CupertinoButton(
onPressed: _onPressed, child: const Text("Card Flip")),
for (int i = 0; i < colorList.length; i++)
Padding(
padding: const EdgeInsets.all(10),
child: Container(
height: 70,
width: 350,
decoration: BoxDecoration(
color: colorList[i],
borderRadius:
const BorderRadius.all(Radius.circular(25))),
)
.animate(target: _toggle ? 0 : 1)
.flipV(
begin: 0,
end: 1,
curve: Curves.fastOutSlowIn,
delay: Duration(milliseconds: 200 * i))
.then(delay: 1000.ms)
.scale(
curve: Curves.bounceOut,
begin: const Offset(1, 1),
end: const Offset(1.5, 1.5),
delay: Duration(milliseconds: 200 * i)),
),
],
),
),
),
);
}
}
Widget.animate() 메서드 체이닝으로 사용 가능한 애니메이션효과 리스트 예시
응용해서 만든 카드 애니메이션.
- 출처: 노마드코더
메서드 체이닝이란?.
메서드 체이닝(Method Chaining)은 객체 지향 프로그래밍에서 자주 사용되는 기술 중 하나입니다. 이 기술은 한 줄에 여러 메서드를 연속적으로 호출하여 하나의 객체에서 다양한 작업을 수행할 수 있게 해줍니다.
일반적으로 메서드 체이닝은 빌더 패턴(Builder Pattern)의 한 형태로 사용됩니다. 이 패턴은 객체의 생성 및 구성을 단순화하고 유연성을 높여줍니다.
메서드 체이닝의 작동 방식은 다음과 같습니다:
- 객체의 메서드가 호출되면, 해당 메서드는 보통 자기 자신(this 또는 self라 불리는)을 반환합니다.
- 이렇게 반환된 객체는 다시 다른 메서드 호출에 사용됩니다.
- 이런 식으로 연쇄적으로 메서드를 호출하며 작업이 계속됩니다.
이렇게 함으로써 여러 메서드 호출을 한 줄에 연속적으로 작성할 수 있으며, 코드의 가독성을 높이고 간결하게 만들 수 있습니다.
예를 들어, 다음은 Dart에서의 메서드 체이닝을 사용한 간단한 예시입니다.
class Calculator {
double _result = 0;
Calculator add(double value) {
_result += value;
return this;
}
Calculator subtract(double value) {
_result -= value;
return this;
}
Calculator multiply(double value) {
_result *= value;
return this;
}
Calculator divide(double value) {
if (value != 0) {
_result /= value;
}
return this;
}
double getResult() {
return _result;
}
}
void main() {
var calc = Calculator();
var result = calc.add(5).multiply(2).subtract(3).divide(2).getResult();
print(result); // 출력: 4.0
}