728x90
๐ ํ์ต ๋ชฉํ
- Flutter์ ์ ๋๋ฉ์ด์ ์์คํ ์ ์ดํดํ๊ณ ๊ฐ๋จํ ์ ๋๋ฉ์ด์ ํจ๊ณผ๋ฅผ ๊ตฌํํ ์ ์๋ค.
- Android(Material), iOS(Cupertino)์ ํ๋ซํผ๋ณ UI ์ฐจ์ด๋ฅผ ์ดํดํ๊ณ , ํ๋ซํผ์ ๋ฐ๋ผ ๋ถ๊ธฐ ์ฒ๋ฆฌํ๋ ๊ธฐ์ด๋ฅผ ๋ฐฐ์ด๋ค.
๐ ์ฃผ์ ๊ฐ๋ ์์ฝ
1. Flutter ์ ๋๋ฉ์ด์ ๊ธฐ๋ณธ ๊ตฌ์กฐ
Flutter์ ์ ๋๋ฉ์ด์ ์ ๋ค์ ์ธ ๊ฐ์ง ํต์ฌ ์์๋ก ๊ตฌ์ฑ๋จ:
๊ฐ๋ | ์ค๋ช |
AnimationController | ์ ๋๋ฉ์ด์ ์ ์คํ/์ ์ง/์๊ฐ์ ์ ์ดํ๋ ์ปจํธ๋กค๋ฌ. ํ๋ ์ ๋จ์๋ก ์ํ๋ฅผ ์ ๋ฐ์ดํธํจ. |
Tween | ์์ ๊ฐ๊ณผ ๋ ๊ฐ์ ์ค์ ํ์ฌ ์ ๋๋ฉ์ด์ ๊ฐ์ ์์ฑํ๋ ๊ฐ์ฒด. ์: 0~1, ์์ ๋ณํ ๋ฑ |
AnimatedWidget | ์ ๋๋ฉ์ด์ ์ํ์ ๋ฐ๋ผ ์๋์ผ๋ก ๋ค์ ๊ทธ๋ ค์ง๋ ์์ ฏ. ๋งค๋ฒ setState() ํธ์ถ ํ์ ์์. |
2. ์์ฃผ ์ฌ์ฉํ๋ ์ ๋๋ฉ์ด์ ์์ ฏ
์์ ฏ๋ช | ์ค๋ช | ์์ ์ฌ์ฉ์ฒ |
FadeTransition | ํฌ๋ช ๋ ์ ๋๋ฉ์ด์ | ํ๋ฉด ์ ํ ์ ํ์ด๋ ์ธ/์์ |
SizeTransition | ์์ ฏ ํฌ๊ธฐ ๋ณ๊ฒฝ | ๋ฒํผ ํ๋/์ถ์ ์ ๋๋ฉ์ด์ |
SlideTransition | ์์ ฏ ์์น ์ด๋ | ์ฌ๋ผ์ด๋๋ก ๋ํ๋๋ ๋ฉ๋ด |
3. ์ ๋๋ฉ์ด์ ํ๋ฆ ๊ฐ๋จ ์์
AnimationController์ Tween์ ํ์ฉํด์ ํ์ด๋ ์ธ(์ ์ ๋ณด์ด๊ธฐ) ํจ๊ณผ๋ฅผ ๊ตฌํํ ์์
class MyFadeWidget extends StatefulWidget {
@override
_MyFadeWidgetState createState() => _MyFadeWidgetState();
}
/// ์ํ ํด๋์ค, ์ ๋๋ฉ์ด์
์ปจํธ๋กค์ ๋ด๋น
class _MyFadeWidgetState extends State<MyFadeWidget> with SingleTickerProviderStateMixin {
late AnimationController _controller; // ์ ๋๋ฉ์ด์
์ปจํธ๋กค๋ฌ ์ ์ธ
late Animation<double> _animation; // ์ ๋๋ฉ์ด์
๊ฐ (ํฌ๋ช
๋)
@override
void initState() {
super.initState();
// ์ ๋๋ฉ์ด์
์ปจํธ๋กค๋ฌ ์์ฑ with 2์ด ์ง์ ์๊ฐ
_controller = AnimationController(
vsync: this, // TickerProvider๋ฅผ ํตํด ์ ๋๋ฉ์ด์
ํ๋ ์ ๋๊ธฐํ
duration: Duration(seconds: 2),
);
// Tween์ ์ฌ์ฉํ์ฌ 0์์ 1๊น์ง ์ ๋๋ฉ์ด์
๊ฐ ์ ๋ฌ
_animation = Tween<double>(begin: 0, end: 1).animate(_controller);
_controller.forward(); // ์ ๋๋ฉ์ด์
์์(ํ์ด๋ ์ธ ํจ๊ณผ)
}
@override
Widget build(BuildContext context) {
return FadeTransition(
opacity: _animation, // ์ ๋๋ฉ์ด์
์ ๋ฐ๋ผ ํฌ๋ช
๋ ๋ณํ
child: Text('Hello, Flutter!'), // ๋ณด์ฌ์ค ํ
์คํธ ์์ ฏ
);
}
@override
void dispose() {
_controller.dispose(); // ๋ฆฌ์์ค ํด์
super.dispose();
}
}
๐งช ์ค์ต ๊ณผ์ ์์
1. ๋ฒํผ ํด๋ฆญ ์ ์์ ๋ณ๊ฒฝ ์ ๋๋ฉ์ด์
- AnimatedContainer๋ฅผ ํ์ฉํ์ฌ ์์, ํฌ๊ธฐ, ์ฌ๋ฐฑ ๋ฑ ๋ถ๋๋ฝ๊ฒ ๋ณ๊ฒฝ
AnimatedContainer(
duration: Duration(seconds: 1),
color: _isClicked ? Colors.blue : Colors.red,
width: 200,
height: 100,
child: ElevatedButton(
onPressed: () {
setState(() {
_isClicked = !_isClicked;
});
},
child: Text('ํด๋ฆญ'),
),
);
2. ํ๋ฉด ์ ํ ์ ํ์ด๋ ํจ๊ณผ ์ ์ฉ
Navigator.of(context).push(
PageRouteBuilder(
pageBuilder: (context, animation, secondaryAnimation) => SecondPage(),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
return FadeTransition(
opacity: animation,
child: child,
);
},
),
);
๐ฑ ํ๋ซํผ๋ณ UI ์ดํด (์ ํ)
ํ๋ซํผ | ๋์์ธ ์์คํ | Flutter ๋์ ์์ ฏ ์์ |
Android | Material Design | Scaffold, AppBar, ElevatedButton |
iOS | Cupertino | CupertinoPageScaffold, CupertinoButton |
ํ๋ซํผ๋ณ UI ๊ตฌํ ์ ์กฐ๊ฑด ๋ถ๊ธฐ:
Widget build(BuildContext context) {
if (Platform.isIOS) {
return CupertinoButton(child: Text('iOS ๋ฒํผ'), onPressed: () {});
} else {
return ElevatedButton(child: Text('Android ๋ฒํผ'), onPressed: () {});
}
}
๋๋ flutter_platform_widgets ํจํค์ง ํ์ฉ.
๐งพ ์ ๋ฆฌ๋ ์ฃผ์ ์์ ฏ/ํด๋์ค/์์ฑ ํ
๋ถ๋ฅ | ์ด๋ฆ | ์ค๋ช |
์ ๋๋ฉ์ด์ ์ ์ด | AnimationController | ์ ๋๋ฉ์ด์ ์ ์๋์ผ๋ก ์ ์ดํจ |
์ ๋๋ฉ์ด์ ๊ฐ ์์ฑ | Tween<T> | ์ ๋๋ฉ์ด์ ๋ฒ์ ์ค์ (ex. 0 ~ 1, ์์) |
์๋ ์์ ฏ ๊ฐฑ์ | AnimatedWidget | ๋ด๋ถ ์ ๋๋ฉ์ด์ ๊ฐ์ด ๋ณ๊ฒฝ๋๋ฉด ์๋ ๊ฐฑ์ |
์์ ฏ ์ ๋๋ฉ์ด์ | AnimatedContainer | ์์ฑ ๋ณ๊ฒฝ ์ ์๋ ์ ๋๋ฉ์ด์ ์ ์ฉ |
์์ ฏ ์ ๋๋ฉ์ด์ | FadeTransition | ํฌ๋ช ๋ ๋ณ๊ฒฝ ์ ๋๋ฉ์ด์ |
์์ ฏ ์ ๋๋ฉ์ด์ | SizeTransition | ์์ ฏ ํฌ๊ธฐ ๋ณ๊ฒฝ ์ ๋๋ฉ์ด์ |
์์ ฏ ์ ๋๋ฉ์ด์ | SlideTransition | ์์น ์ด๋ ์ ๋๋ฉ์ด์ |
์ ๋๋ฉ์ด์ ์ปค๋ธ | CurvedAnimation | ์๋ ๊ณก์ ์ ์ฉ (ex. ease-in, bounce ๋ฑ) |
๐ ์ฐธ๊ณ ๋งํฌ
- Flutter ๊ณต์ ์ ๋๋ฉ์ด์
๋ฌธ์:
๐ https://docs.flutter.dev/ui/animations/overview - ์ ๋๋ฉ์ด์
์์ ๋ชจ์ (Flutter Gallery):
๐ https://gallery.flutter.dev/#/animations
'Flutter + Dart > Flutter + Dart ๊ณต๋ถ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
json ํ์ผ์ .dart์ ๋ณ์๋ก ๊ฐ์ ธ์ค๊ธฐ (0) | 2025.05.19 |
---|---|
์์ ฏ ์ ๋ ฌ - ์ ์ฒด ์ฑ์ฐ๊ธฐ, ์ข์ธก ์๋จ ์ ๋ ฌ (0) | 2025.05.19 |
ํ ๋ง ๋ฐ ์คํ์ผ ์ ์ฉ, ์ปค์คํ ์์ ฏ ์ ์ ๊ธฐ์ด (0) | 2025.05.16 |
flutter ๋ฌ๋ ฅ ์ถ๊ฐํ๊ธฐ (0) | 2025.05.15 |
Provider (0) | 2025.05.15 |