Animasi pada Flutter
Pemrograman Mobile 2
Muhamad Saad Nurul Ishlah, M.Comp.
Dept. Sistem Informasi & Dept. Ilmu Komputer, Universitas Pakuan
Agenda Kuliah
- Drawing-based vs Code-based Animation
- Implicit Animation
- Explicit Animation
- Memilih pendekatan Animasi yang sesuai
- Package animasi
Drawing-based vs Code-based Animation
Drawing-based Animation
- Drawing-based Animation
- Animated graphics
- Vectors
- Karakter
- Sesuatu yang "digambar" dan kemudian dianimasikan
https://rive.app/community/3411-7160-safe-icon/
Code-based Animation
- Code-based Animation
- Widget
- Layout
- Styles
- dll
https://medium.com/flutter-community/flutter-animations-comprehensive-guide-cb93b246ca5d
Animasi Implisit
(Implicit Animation)
Implicit Animation
- Animasi implisit dengan widget yang siap digunakan
- Widget animasi bawaan
- Animasi implisit dengan TweenAnimationBuilder
- Menambahkan Animasi pada widget apapun
Implicit Animation - Ready-to-use Widgets`
- Widget disebut AnimatedFoo
- Foo menunjuk pada Properti yang dapat dianimasikan
- Contoh:
- Container > AnimatedContainer
- Padding > AnimatedContainer
- Positioned > AnimatedPositioned
- dll
Implicit Animation - Ready-to-use Widgets
- Animasi di sebelah menggunakan
- AnimatedContainer
- AnimatedPositioned
- AnimatedDefaultTextStyle
Implicit Animation - Ready-to-use Widgets
AnimatedPositioned(
top: selectedItemIndex * itemHeight,
left: 0,
right: 0,
duration: const Duration(milliseconds: 200),
curve: Curves.easeInOut,
child: //...
),
//...
AnimatedContainer(
duration: const Duration(milliseconds: 200),
curve: Curves.easeInOut,
decoration: BoxDecoration(
color: selectedItemIndex == i ? yellow : pink,
border: Border.all(
color: selectedItemIndex == i
? Colors.white
: Colors.transparent,
width: 2,
),
),
child: AnimatedDefaultTextStyle(
duration: const Duration(milliseconds: 200),
style: TextStyle(
color: selectedItemIndex == i
? Colors.black
: Colors.white,
),
child: const Text('Featured!'),
),
),
// dibungkus dalam "InkWell"
onTap: () => setState(() => selectedItemIndex = i),
Implicit Animation - Ready-to-use Widgets
Daftar Widget AnimatedFoo
AnimatedAlign
AnimatedContainer
AnimatedDefaultTextStyle
AnimatedOpacity
AnimatedPadding
-
AnimatedPhysicalModel
-
AnimatedPositioned
-
AnimatedPositionDirectional
-
AnimatedSize
Bagaimana jika ingin menganimasikan widget lain yang tidak terdapat pada list?
Implicit Animation - TweenAnimationBuilder
- TweenAnimationBuilder memungkinkan untuk melakukan animasi terhadap property dari widget apapun menggunakan kelas Tween
- Tween diambil dari "Between" - In Between Animation
- Memberikan nilai awal dan akhir -
begin
danend
Implicit Animation - TweenAnimationBuilder
TweenAnimationBuilder(
duration: const Duration(milliseconds: 200),
tween: Tween<double>(begin: 0.01, end: _sliderValue),
child: Container(
decoration: BoxDecoration(
//...
),
child: Slider(
value: _sliderValue,
min: 0.01,
onChanged: (value) {
setState(() => _sliderValue = value);
},
),
),
builder: (BuildContext context, double? value, Widget? child) {
return ClipRect(
child: BackdropFilter(
filter: ImageFilter.blur(
sigmaX: 40 * (value ?? 0.01),
sigmaY: 40 * (value ?? 0.01),
),
child: child,
),
);
},
);
Animasi Eksplisit
(Explicit Animation)
Explicit Animation
- Implicit Animation (AnimatedFoo & TweenAnimationBuilder) memulai animasi secara otomatis dengan mengubah nilai property tertentu
- Explicit Animation memulai animasi jika diminta secara eksplisit (explicit)
- AnimationController digunakan untuk memulai dan mengontrol animasi
- Explicit Animation juga memiliki widget yang siap digunakan (ready-to-use/bawaan) dan widget yang perlu kustomisasi
AnimationController
- AnimationController memungkinkan kita untuk mengontrol animasi
- memerlukan property vsync (TickerProvider)
- Ticker pada dasarnya melacak rendering frame Flutter dan memungkinkan pengontrol untuk mengikuti ticker itu dan melakukan animasi melaluinya dalam durasi yang ditentukan, sementara secara linier menghasilkan nilai antara nilai lowerBound dan upperBound yang secara default 0 & 1.
AnimationController({
double? value,
this.duration,
this.reverseDuration,
this.debugLabel,
this.lowerBound = 0.0,
this.upperBound = 1.0,
this.animationBehavior = AnimationBehavior.normal,
required TickerProvider vsync,
})
AnimationController
Callback Function | Fungsi |
---|---|
forward() | menjalankan animasi secara maju |
reverse() | menjalankan animasi secara mundur |
stop() | menghentikan animasi |
repeat() | mengulang animasi selama terlihat |
reset() | mengembalikan animasi ke nilai lowerBound |
Menset nilai animasi | |
Mengakses beberapa nilai getter untuk mengetahui state dari animasi, seperti: isAnimating, isComplete, isDismissed, dll |
Explicit Animation - Widget Bawaan
- Widget bawaan dengan pola FooTransition
- Foo menunjuk pada property yang dapat dianimasikan
- Contoh:
- AlignTransition
- PositionedTransition
Explicit Animation - Widget Bawaan
class ExplicitAnimations extends StatefulWidget {
const ExplicitAnimations({Key? key}) : super(key: key);
@override
State<ExplicitAnimations> createState() => _ExplicitAnimationsState();
}
class _ExplicitAnimationsState extends State<ExplicitAnimations>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late final Animation<AlignmentGeometry> _alignAnimation;
late final Animation<double> _rotationAnimation;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(milliseconds: 800),
vsync: this,
)..repeat(reverse: true);
_alignAnimation = Tween<AlignmentGeometry>(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
).animate(
CurvedAnimation(
parent: _controller,
curve: Curves.easeInOutCubic,
),
);
_rotationAnimation = Tween<double>(begin: 0, end: 2).animate(
CurvedAnimation(
parent: _controller,
curve: Curves.easeInOutCubic,
),
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return BlurContainer(
containerHeight: 200,
child: AlignTransition(
alignment: _alignAnimation,
child: RotationTransition(
turns: _rotationAnimation,
child: const Rectangle(
color1: pink,
color2: pinkDark,
width: 50,
height: 50,
),
),
),
);
}
}
Explicit Animation - Bawaan
Daftar Widget FooTransition
-
AlignTransition
-
DecoratedBoxTransition
-
DefaultTextStyleTransition
-
FadeTransition
-
PositionedTransition
-
RelativePositionedTransition
-
RotationTransition
-
ScaleTransition
-
SizeTransition
-
SlideTransition
-
StatusTransitionWidget
Bagaimana jika ingin menganimasikan widget lain yang tidak terdapat pada list?
Explicit Animation
Tidak terdapat GradientTransition, tapi bisa dibuat dengan AnimatedBuilder & AnimatedWidget
Explicit Animation - AnimationBuilder
class AnimatedBuilderExample extends StatefulWidget {
const AnimatedBuilderExample({Key? key}) : super(key: key);
@override
_AnimatedBuilderExampleState createState() => _AnimatedBuilderExampleState();
}
class _AnimatedBuilderExampleState extends State<AnimatedBuilderExample>
with SingleTickerProviderStateMixin {
late final AnimationController _controller;
@override
void initState() {
_controller = AnimationController(
duration: const Duration(milliseconds: 500),
vsync: this,
)..repeat(reverse: true);
super.initState();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _controller,
builder: (BuildContext context, Widget? child) {
return Container(
height: 100,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: const [purple, pink, yellow],
stops: [0, _controller.value, 1],
),
borderRadius: BorderRadius.circular(15),
border: Border.all(color: Colors.white),
),
);
},
);
}
}
Explicit Animation - AnimatedWidget
- AnimatedWidget merupakan Widget yang dibuat dengan menurunkan StatefulWidget
Explicit Animation - AnimatedWidget
- AnimatedWidget merupakan Widget yang dibuat dengan menurunkan StatefulWidget
- GradientTransition menggunakan AnimatedWidget
Explicit Animation - AnimationWidget
class GradientTransition extends AnimatedWidget {
final Animation<double> stop;
const GradientTransition({
Key? key,
required this.stop,
}) : super(key: key, listenable: stop);
@override
Widget build(BuildContext context) {
return Container(
height: 100,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: const [purple, pink, yellow],
stops: [0, stop.value, 1],
),
),
);
}
}
// Kemudian gunakan dengan mempassing AnimationController
GradientTransition(stop: _controller),
Demo Kode
Contoh Implementasi Animasi
- GitHub: https://github.com/flutter/samples/tree/main/animations
- Dartpad: https://dartpad.dev/?id=c9bb2627d4f38319bab7dc456c5092cd
Memilih Pendekatan Animasi yang Sesuai
Memilih Drawing atau Code
- Apakah bentuk Animasi seperti gambar grafik (2D, 3D)?
- Gunakan Drawing-based animation 3rd party package
- Rive, Lottie, dll
- Apakah animasi berkaitan dengan layout, widget, style widget, warna, border, text, dll?
- Gunakan Code-based animation
Memilih Implicit atau Explicit
- Apakah animasi berulang ketika visible?
- Apakah animasi berbentuk discontinuous animation (animasi tidak kembali ke tempat mulai)?
- Apakah terdapat multiple widget yang dianimasikan?
Jika jawaban untuk semua pertanyaan tersebut adalah ya, maka gunakan Explicit Animation
Memilih Widget Bawaan atau Kustom
- Apakah sudah terdapat widget bawaan untuk menganimasikan?
- Jika ya, gunakan widget bawaan
- AnimatedFoo
- FooTransition
- Jika tidak, gunakan widget kustom
- AnimationController
- AnimationBuilder
- AnimatedWidget
- Jika ya, gunakan widget bawaan
Memilih Widget Bawaan atau Kustom
Memilih Implicit atau Explicit
Memilih Implicit atau Explicit
Diskusi
Ada pertanyaan?
Referensi
- Gibbon, A. F. (2022, May 28). How to choose which Flutter Animation Widget is right for you?. Retrieved October 19, 2022, from https://medium.com/flutter/how-to-choose-which-flutter-animation-widget-is-right-for-you-79ecfb7e72b5
- Introduction to Animations. https://docs.flutter.dev/development/ui/animations, diakses 19 Oktober 2022
Roaa. (2022, April 24). Flutter Animations Comprehensive Guide. Medium. Retrieved October 19, 2022, from https://medium.com/flutter-community/flutter-animations-comprehensive-guide-cb93b246ca5d
Terima Kasih
Animasi pada Flutter
By M. Saad Nurul Ishlah
Animasi pada Flutter
- 248