Kami menerapkan CircularRevealAnimation on Flutter dan secara bersamaan menerbitkan perpustakaan di pub.dev

Android memiliki fitur yang sangat menarik dari animasi View yang disebut CircularRevealAnimation - secara harfiah "pengungkapan sirkuler." Flutter, pada gilirannya, meskipun memiliki kemampuan yang kaya untuk menjiwai widget, tidak menyediakan animasi seperti itu di luar kotak.



Artikel ini akan menunjukkan cara menerapkan animasi tersebut menggunakan Flutter dan menerbitkan perpustakaan di pub.dev untuk akses dan distribusi yang mudah.


Implementasi animasi


Di Flutter, semuanya adalah widget. Dan animasi tidak terkecuali. Oleh karena itu, kami membuat kelas CircularRevealAnimation , yang akan memperluas kelas StatelessWidget .


Memulai, menghentikan, dan kontrol animasi lainnya dilakukan menggunakan AnimationController . Untuk membuat AnimationController Anda harus mewarisi dari StatefulWidget dan menambahkan kelas khusus SingleTickerProviderStateMixin ke State .


CircularRevealAnimation kelas animasi kami tidak akan bertanggung jawab untuk mengelola animasi sendiri, tetapi akan menerima Animation<double> sebagai parameter konstruktor yang diperlukan, sehingga tidak perlu mewarisi dari StatefulWidget . Ini dilakukan agar CircularRevealAnimation dapat dengan mudah digabungkan dengan animasi lain yang menggunakan AnimationController sama. Misalnya, gabungkan animasi pengungkapan dengan animasi perubahan transparansi.


Parameter penting lain dari konstruktor CircularRevealAnimation adalah child , yang merupakan widget anak dari animasi kami, dan yang akan muncul atau hilang. Secara umum, di Flutter, banyak widget memiliki parameter turunan. Widget tersebut memungkinkan Anda untuk mengubah perilaku, rendering, atau tata letak widget anak. Atau tambahkan animasi, seperti yang terjadi dengan CircularRevealAnimation .


Selain itu, untuk menentukan animasi, parameter seperti pusat pembukaan (atau penutup) animasi, serta radius minimum dan maksimum pembukaan, akan diperlukan. Parameter ini opsional dan dapat ditentukan sebagai null atau tidak ditentukan sama sekali saat membuat animasi. Dalam hal ini, nilai default akan digunakan: pusat pengungkapan akan berada di tengah widget, jari-jari minimum akan dipotong menjadi nol, dan jari-jari maksimum akan sama dengan jarak dari pusat pengungkapan ke titik puncak widget yang paling jauh dari pusat pengungkapan.


Algoritma perhitungan radius maksimum default adalah sebagai berikut. Pertama, jarak horizontal dan vertikal dari pusat ke titik terjauh dari pusat pengungkapan dihitung, dan kemudian diagonal dihitung oleh teorema Pythagoras.


 static double calcMaxRadius(Size size, Offset center) { final w = max(center.dx, size.width - center.dx); final h = max(center.dy, size.height - center.dy); return sqrt(w * w + h * h); } 

Sekarang Anda perlu menerapkan pemotongan widget di dalam lingkaran selama rendering. Kelas ClipPath akan membantu kami dalam hal ini, yang memungkinkan Anda untuk memotong widget berdasarkan templat yang sewenang-wenang. Sebagai parameter, widget ini dilewati clipper (sedikit lebih lambat) dan child adalah widget anak yang perlu dipangkas.


Parameter clipper dari widget ClipPath menentukan bagaimana widget anak akan dipangkas. Untuk membuat template pemangkasan Anda sendiri, buat kelas CircularRevealClipper , yang mewarisi kelas CustomClipper<Path> dan mendefinisikan kembali metode Path getClip(Size size) . Metode ini mengembalikan Path membatasi area tanam. Dalam kasus kami, wilayah ini adalah lingkaran dengan pusat yang diberikan. Untuk menghitung jari-jari lingkaran, Anda perlu mengetahui nilai animasi saat ini. Nilai ini diteruskan ke CircularRevealClipper sebagai parameter fraction . Jari-jari lingkaran dihitung menggunakan interpolasi linier antara jari-jari minimum dan maksimum.


Setelah itu, mari kita beralih ke implementasi widget. Lebih mudah menggunakan AnimatedBuilder untuk membuat animasi. Konstruktor AnimatedBuilder menerima objek Animation<double> dan builder digunakan untuk membuat widget berdasarkan nilai animasi saat ini. Dalam builder kami membuat ClipPath dan meneruskan nilai animasi ( fraction ) saat ini ke CircularRevealClipper .


 class CircularRevealAnimation extends StatelessWidget { ... @override Widget build(BuildContext context) { return AnimatedBuilder( animation: animation, builder: (BuildContext context, Widget _) { return ClipPath( clipper: CircularRevealClipper( fraction: animation.value, center: center, minRadius: minRadius, maxRadius: maxRadius, ), child: this.child, ); }, ); } } 

Ini melengkapi pembuatan CircularRevealAnimation . Masih menggunakannya. Untuk melakukan ini, buat StatefulWidget , AnimationController dan berikan AnimationController ke CircularRevealAnimation .


Contoh penggunaan
 import 'package:flutter/material.dart'; import 'package:circular_reveal_animation/circular_reveal_animation.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'CRA Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(), ); } } class MyHomePage extends StatefulWidget { @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin { AnimationController animationController; Animation<double> animation; @override void initState() { super.initState(); animationController = AnimationController( vsync: this, duration: Duration(milliseconds: 1000), ); animation = CurvedAnimation( parent: animationController, curve: Curves.easeIn, ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("CRA Demo"), ), body: Padding( padding: const EdgeInsets.all(16.0), child: CircularRevealAnimation( minRadius: 12, maxRadius: 200, center: Offset(0, 300), child: Container(color: Colors.red), animation: animation, ), ), floatingActionButton: FloatingActionButton(onPressed: () { if (animationController.status == AnimationStatus.forward || animationController.status == AnimationStatus.completed) { animationController.reverse(); } else { animationController.forward(); } }), ); } } 

Aplikasi demo Github .


Pembuatan perpustakaan


Untuk membuat perpustakaan Dart atau Flutter, Anda perlu menambahkan file pubspec.yaml ke direktori yang sama dengan direktori lib dengan file Dart. File ini berisi deskripsi perpustakaan, informasi tentang penulis dan dependensi.


Ini juga merupakan praktik yang baik untuk membuat file yang mendefinisikan API publik. File ini terletak di folder lib dan termasuk nama perpustakaan dan daftar file yang perlu dimasukkan dalam API publik. Semua file Dart lainnya ditempatkan di direktori src . Ini tidak hanya menyembunyikan file yang tidak termasuk dalam API publik, tetapi juga memungkinkan Anda untuk mengimpor pustaka menggunakan ekspresi import tunggal. Isi file ini:


 library circular_reveal_animation; export 'package:circular_reveal_animation/src/circular_reveal_animation.dart'; 

Anda dapat membaca lebih lanjut tentang membuat perpustakaan di Dart di sini .


Terbitkan ke pub.dev


Menerbitkan perpustakaan Dart ke pub.dev sangat sederhana. Yang perlu Anda lakukan adalah menjalankan perintah flutter packages pub publish dari direktori root perpustakaan. Penerbitan dilakukan atas nama akun Google, jadi selama proses publikasi tautan akan diberikan yang harus dibuka di browser dan masuk ke Google. Selanjutnya, pembaruan hanya dapat dipublikasikan menggunakan akun yang atas nama versi pertama diposting.


Sebelum menerbitkan, Anda disarankan untuk memverifikasi bahwa perpustakaan benar menggunakan flutter packages pub publish --dry-run .


Setelah menjalankan flutter packages pub publish perpustakaan akan segera tersedia di pub.dev. Dan, seperti yang tertulis dalam dokumentasi, "Penerbitan selamanya" - nanti Anda hanya dapat mengunggah versi baru. Versi yang lebih lama juga akan tersedia.


Meskipun penerbitan perpustakaan terlihat sederhana, ia juga dapat memiliki jebakan. Misalnya, ketika menerbitkan versi pertama, saya dikeluarkan beberapa poin di peringkat karena deskripsi perpustakaan (di pubspec.yaml ) terlalu pendek.


Anda dapat membaca lebih lanjut tentang menerbitkan perpustakaan di sini .


Sebenarnya, perpustakaan circular_reveal_animation di pub.dev dan github.com .


PS: Saya menggunakan ```java {...} ``` untuk menyorot kode Dart. Alangkah baiknya menambahkan highlight kode Dart di habr.com.

Source: https://habr.com/ru/post/id452072/


All Articles