Untuk teman-teman yang akan baru memulai belajar Flutter silahkan masuk ke artikel ini dulu ya teman-teman ➡ Aplikasi Pertamaku “Halo Semuaaa…“. Jika sudah yuk lanjut baca artikel ini…
Jangan lupa baca artikel sebelumnya ya teman-teman ➡ Membuat Animasi Transisi Route.
Simulasi fisika dapat memberikan pengalaman interaksi pengguna pada aplikasi sehingga terasa realistis dan interaktif. Dalam hal ini, kita akan menganimasikan widget agar berfungsi seolah-olah widget tersebut terpasang ke pegas atau jatuh kembali karena tarikan gravitasi. Langkah-langkahnya sebagai berikut:
- Melakukan Set Up pada Animation Controller.
- Menggeser widget menggunakan gestures.
- Membuat animasi widget.
- Menghitung kecepatan untuk mensimulasikan gerakan pegas.
1. Melakukan Set Up pada Animation Controller
Dimulai dengan stateful widget yang disebut DraggableCard
:
Langkah selanjutnya, buat kelas _DraggableCardState
menjadi extend dari SingleTickerProviderStateMixin. Kemudian buat AnimationController di dalam initState
dan set vsync
ke this
.
(Modifikasi dan tambahkan cuplikan kode berikut pada kelas _DraggableCardState
)
class _DraggableCardState extends State<DraggableCard> with SingleTickerProviderStateMixin { AnimationController _controller; @override void initState() { _controller = AnimationController(vsync: this, duration: Duration(seconds: 1)); super.initState(); } @override void dispose() { _controller.dispose(); super.dispose(); } //...
2. Menggeser Widget Menggunakan Gestures
Agar sebuah widget dapat digerakkan saat digeser, maka kita perlu menambahkan field Alignment ke kelas _DraggableCardState
:
Alignment _dragAlignment = Alignment.center;
Selanjutkan kita tambahkan GestureDetector yang fungsinya untuk menangani callback onPanDown
, onPanUpdate
, danonPanEnd
. Supaya dapat mengatur alignment, maka MediaQuery untuk mendapatkan ukuran widget, dan bagi dengan nilai 2 (fungsinya untuk mengonversi unit “piksel yang ditarik” ke koordinat yang digunakan Align). Kemudian, set alignment
widget Align
ke _dragAlignment
:
(Modifikasi dan tambahkan cuplikan kode berikut pada kelas _DraggableCardState
)
@override Widget build(BuildContext context) { var size = MediaQuery.of(context).size; return GestureDetector( onPanDown: (details) {}, onPanUpdate: (details) { setState(() { _dragAlignment += Alignment( details.delta.dx / (size.width / 2), details.delta.dy / (size.height / 2), ); }); }, onPanEnd: (details) {}, child: Align( alignment: _dragAlignment, child: Card( child: widget.child, ), ), ); }
3. Membuat Animasi Widget
Nantinya saat widget digeser kemudian dilepas, akan memberikan efek spring yang membuat widget tersebut kembali ke tengah.
Selanjutnya tambahkan field Animation<Alignment>
dan method _runAnimation
fungsinya untuk mendefinisikan Tween
yang menginterpolasi antara titik tempat widget ditarik ke titik di tengah.
(Modifikasi dan tambahkan cuplikan kode berikut pada kelas _DraggableCardState
)
Animation<Alignment> _animation; void _runAnimation() { _animation = _controller.drive( AlignmentTween( begin: _dragAlignment, end: Alignment.center, ), ); _controller.reset(); _controller.forward(); }
Selanjutnya, modifikasi _dragAlignment
ketika AnimationController
menghasilkan nilai:
@override void initState() { super.initState(); _controller = AnimationController(vsync: this, duration: Duration(seconds: 1)); _controller.addListener(() { setState(() { _dragAlignment = _animation.value; }); }); }
Lalu, buat widget Align
yang di dalamnya menggunakan field _dragAlignment
:
child: Align( alignment: _dragAlignment, child: Card( child: widget.child, ), ),
Terakhir, modifikasi GestureDetector
untuk mengelola animation controller:
onPanDown: (details) { _controller.stop(); }, onPanUpdate: (details) { setState(() { _dragAlignment += Alignment( details.delta.dx / (size.width / 2), details.delta.dy / (size.height / 2), ); }); }, onPanEnd: (details) { _runAnimation(); },
4. Menghitung Kecepatan Untuk Mensimulasikan Gerakan Pegas
Langkah terakhir adalah melakukan sedikit penghitungan kecepatan widget setelah selesai digeser, tujuannya agar widget melanjutkan gerakan secara realistis pada kecepatan tertentu sebelum widget dilepas kembali. (Method _runAnimation
sudah memiliki sets arah dengan menyetel animasi alignment awal dan akhir)
Pertama, lakukan imporphysics
package:
import 'package:flutter/physics.dart';
Perlu teman-teman ketahui, callback onPanEnd
menyediakan objek DragEndDetails yang befungsi untuk memberikan kecepatan pointer saat berhenti menyentuh layar. Kecepatannya memiliki satuan piksel per detik, tetapi widget Align
tidak menggunakan satuan piksel melainkan menggunakan nilai koordinat antara [-1.0, -1.0] dan [1.0, 1.0], di mana [0.0, 0.0] mewakili titik pusat. Size
yang dihitung pada langkah 2 digunakan untuk mengubah piksel menjadi nilai koordinat pada range yang sudah ditentukan.
Selanjutnya, AnimationController
memiliki method animateWith()
yang dapat diberikan class SpringSimulation:
void _runAnimation(Offset pixelsPerSecond, Size size) { _animation = _controller.drive( AlignmentTween( begin: _dragAlignment, end: Alignment.center, ), ); // Calculate the velocity relative to the unit interval, [0,1], // used by the animation controller. final unitsPerSecondX = pixelsPerSecond.dx / size.width; final unitsPerSecondY = pixelsPerSecond.dy / size.height; final unitsPerSecond = Offset(unitsPerSecondX, unitsPerSecondY); final unitVelocity = unitsPerSecond.distance; const spring = SpringDescription( mass: 30, stiffness: 1, damping: 1, ); final simulation = SpringSimulation(spring, 0, 1, -unitVelocity); _controller.animateWith(simulation); }
Jangan lupa untuk memanggil _runAnimation()
yang di dalamnya terdapat velocity dan size:
onPanEnd: (details) { _runAnimation(details.velocity.pixelsPerSecond, size); },
Berikut cuplikan kode dan simulasinya, jika teman-teman menggunakan VSCode jalankan projectnya dengan menekan F5, klik hot reload (⚡) atau klik tombol ▶, maka berikut hasil akhirnya (klik logo Flutter dan geser secara random ke kiri, kanan, atas dan bawah lalu lepas logo tersebut):
Jika ada pertanyaan silahkan komen dan jika artikel ini dirasa bermanfaat, jangan lupa like dan sharenya ya teman-teman. ??????? Sampai bertemu di artikel selanjutnya.
Terima Kasih, Assalamu’alaykum… Salam KODINGINDONESIA
Referensi : https://flutter.dev//