Flutter 의 애니메이션에서는 크게 암시적 애니메이션과 명시적 애니메이션으로 구분된다.
암시적 애니메이션(Implict Animations)
- 개발자가 세부 동작을 구현하지 않아도 위젯에서 임의로 애니메이션 효과가 나타난다.
Animated~ 로 붙어있는 위젯은 애니메이션이 제공되는 위젯이다.
자주 사용할 위젯 예시
AnimatedAlign
GestureDetector(
onTap: () {
setState(() {
selected = !selected;
});
},
child: Container(
height: 300,
width: double.infinity,
color: Colors.blue,
child: AnimatedAlign(
// alignment 속성이 변경되면 애니메이션 진행이 됨
alignment: selected ? Alignment.topLeft : Alignment.bottomRight,
curve: Curves.easeIn, // 애니메이션 효과
duration: Duration(seconds: 5), // 애니메이션이 진행되는 시간
child: Container(
width: 50,
height: 50,
color: Colors.red,
),
),
),
);
AnimatedContainer
GestureDetector(
onTap: () {
setState(() {
selected = !selected;
});
},
child: Container(
height: 300,
width: double.infinity,
color: Colors.purple,
// 바깥 컨테이너에서 alignment 속성이 주어지지 않으면 내부의 container 가 다 덮어씌워짐
alignment: Alignment.center,
child: AnimatedContainer(
// 속성 값 변경되면 애니메이션 진행(alignment, height, width, decoration 등)
alignment: selected ? Alignment.topLeft : Alignment.bottomRight,
height: selected ? 200 : 100,
width: selected ? 200 : 100,
decoration: BoxDecoration(
color: selected ? Colors.green : Colors.red,
borderRadius: BorderRadius.circular(selected ? 20 : 0),
),
curve: Curves.linear,
duration: Duration(seconds: 2), // 애니메이션이 진행되는 시간
child: Container(
width: 50,
height: 50,
color: Colors.amber,
),
),
),
);
Hero
- 다른 화면으로 이동할 때 위젯을 연결하는 애니메이션 효과 제공 - tag 속성을 이용하여 연결을 해야한다
class HeroExample extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) {
return HeroPage();
},
));
},
child: Container(
child: Row(
children: [
Hero(
// tag 설정
tag: 'sample-image',
child: SizedBox(
width: 100,
height: 100,
child: Image.network(
'https://picsum.photos/200/200',
fit: BoxFit.cover,
),
),
),
SizedBox(width: 10),
Text('상품명'),
SizedBox(width: 10),
Text('200,0000원'),
],
),
),
);
}
}
class HeroPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
children: [
Hero(
// tag 설정
tag: 'sample-image',
child: AspectRatio(
aspectRatio: 1,
child: Image.network(
'https://picsum.photos/200/200',
fit: BoxFit.cover,
),
),
),
],
),
);
}
}
명시적 애니메이션(Explicit Animations)
- 개발자가 애니메이션의 세부 동작을 모두 직접 구현하는 방식이다.
AnimationController 객체로 애니메이션 진행상태 제어
class ExplictExample extends StatefulWidget {
@override
State<ExplictExample> createState() => _ExplictExampleState();
}
class _ExplictExampleState extends State<ExplictExample>
with TickerProviderStateMixin {
late final animationController = AnimationController(
vsync: this,
duration: Duration(seconds: 10),
);
// 애니메이션 진행될 때 0 부터 300 까지 value 값이 증가 됨
late final animation =
Tween<double>(begin: 0, end: 300).animate(animationController);
@override
void dispose() {
animationController.dispose(); // 메모리 소거
super.dispose();
}
@override
Widget build(BuildContext context) {
return GestureDetector(
// 위젯을 꾹 눌렀을 때
onLongPressDown: (details) {
// 애니메이션 진행
animationController.forward();
},
// 위젯을 꾹 누르고 손을 뗄 때
onLongPressEnd: (details) {
// 애니메이션 멈춤
animationController.stop();
},
// 위젯을 꾹 누르다가 취소될 때
onLongPressCancel: () {
// 애니메이션 멈춤
animationController.stop();
},
// 두 번 터치했을 때
onDoubleTap: () {
// 애니메이션 값이 초기화
animationController.reset();
},
child: Container(
width: double.infinity,
height: 300,
color: Colors.blue,
alignment: Alignment.center,
child: Stack(
children: [
Container(
width: 50,
height: 300,
color: Colors.red,
),
AnimatedBuilder(
// animation 값이 변경될 때마다 builder 가 호출된다
animation: animation,
builder: (context, child) {
return Container(
width: 50,
height: animation.value,
color: Colors.green,
);
},
),
],
),
),
);
}
}
꾹 누름(초록색 게이지 움직임) -> 마우스 뗌(초록색 게이지 멈춤) -> 마우스 두 번 클릭(초록색 게이지 초기화)
'Flutter' 카테고리의 다른 글
[flutter] Clean Architecture 에서 사용하는 개념 잡고가기 (1) | 2024.12.27 |
---|---|
[flutter] 위젯이 재빌드되는 횟수 파악하기 (0) | 2024.12.23 |
[flutter] 페이지 뒤로가기할 때 새로고침 하기 (0) | 2024.12.17 |
[flutter] BottomSheet 에 SafeArea 지정하는 방법 (0) | 2024.12.12 |
[InAppWebView] 기본 설정 (1) | 2024.12.05 |
댓글