Implementamos CircularRevealAnimation no Flutter e publicamos simultaneamente a biblioteca em pub.dev

O Android tem um recurso muito interessante da animação do View chamado CircularRevealAnimation - literalmente "divulgação circular". O Flutter, por sua vez, embora tenha recursos avançados para animar widgets, não fornece essa animação imediatamente.



Este artigo mostra como implementar essa animação usando o Flutter e publica a biblioteca no pub.dev para facilitar o acesso e a distribuição.


Implementação de animação


No Flutter, tudo é um widget. E a animação não é exceção. Portanto, criamos a classe CircularRevealAnimation , que estenderá a classe StatelessWidget .


Iniciar, parar e outros controles de animação são feitos usando o AnimationController . Para criar um AnimationController você precisa herdar do StatefulWidget e adicionar uma classe especial SingleTickerProviderStateMixin ao State .


Nossa classe de animação CircularRevealAnimation não gerenciará de forma independente a animação, mas receberá a Animation<double> como um parâmetro obrigatório do construtor, portanto, não há necessidade de herdar do StatefulWidget . Isso é feito para que o CircularRevealAnimation possa ser facilmente combinado com outras animações que usam o mesmo AnimationController . Por exemplo, combine animação de divulgação com animação de alteração de transparência.


Outro parâmetro importante do construtor CircularRevealAnimation é o child , que é um widget filho da nossa animação e que aparecerá ou desaparecerá. Em geral, no Flutter, muitos widgets possuem um parâmetro child . Esses widgets permitem alterar o comportamento, a renderização ou o layout de um widget filho. Ou adicione animação, como acontece com CircularRevealAnimation .


Além disso, para especificar uma animação, você precisará de parâmetros como o centro da abertura (ou fechamento) da animação, bem como os raios mínimo e máximo de divulgação. Esses parâmetros são opcionais e podem ser especificados como null ou não especificados ao criar uma animação. Nesse caso, os valores padrão serão usados: o centro de divulgação estará no centro do widget, o raio mínimo será zerado e o raio máximo será igual à distância do centro de divulgação ao vértice do widget que está mais distante do centro de divulgação.


O algoritmo de cálculo do raio máximo padrão é o seguinte. Primeiro, as distâncias horizontal e vertical do centro ao vértice mais distante do centro de divulgação são calculadas e, em seguida, a diagonal é calculada pelo teorema de Pitágoras.


 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); } 

Agora você precisa implementar o corte do widget dentro do círculo durante a renderização. A classe ClipPath nos ajudará com isso, o que permite cortar o widget de acordo com um modelo arbitrário. Como parâmetros, esse widget recebe o clipper (um pouco mais tarde) e child é o widget filho que precisa ser cortado.


O parâmetro clipper do widget ClipPath determina como o widget filho será cortado. Para criar seu próprio modelo de corte, crie a classe CircularRevealClipper , que herda a CustomClipper<Path> e redefina o Path getClip(Size size) . Este método retorna um Path delimitando a área de corte. No nosso caso, essa região é um círculo com um determinado centro. Para calcular o raio de um círculo, você precisa saber o valor atual da animação. Este valor é passado para CircularRevealClipper como o parâmetro de fraction . O raio do círculo é calculado usando interpolação linear entre os raios mínimo e máximo.


Depois disso, vamos seguir para a implementação do widget. É conveniente usar o AnimatedBuilder para criar uma animação. O construtor AnimatedBuilder aceita o objeto Animation<double> e o builder usado para criar widgets com base no valor atual da animação. No builder criamos um ClipPath e passamos o valor atual da animação ( fraction ) para o 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, ); }, ); } } 

Isso completa a criação da CircularRevealAnimation . Resta usá-lo. Para fazer isso, crie um StatefulWidget , AnimationController e passe o AnimationController para CircularRevealAnimation .


Exemplo de uso
 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(); } }), ); } } 

Aplicativo de demonstração do Github .


Criação de biblioteca


Para criar uma biblioteca Dart ou Flutter, você precisa adicionar o arquivo pubspec.yaml ao mesmo diretório que o diretório lib com os arquivos Dart. Este arquivo contém uma descrição da biblioteca, informações sobre autores e dependências.


Também é uma boa prática criar um arquivo que define uma API pública. Este arquivo está localizado na pasta lib e inclui o nome da biblioteca e uma lista de arquivos que precisam ser incluídos na API pública. Todos os outros arquivos Dart são colocados no diretório src . Isso não apenas oculta arquivos que não estão incluídos na API pública, mas também permite importar a biblioteca usando uma única expressão de import . O conteúdo deste arquivo :


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

Você pode ler mais sobre a criação de bibliotecas no Dart aqui .


Publicar em pub.dev


A publicação de uma biblioteca Dart no pub.dev é muito simples. Tudo o que você precisa fazer é executar o comando flutter packages pub publish partir do diretório raiz da biblioteca. A publicação é realizada em nome de uma conta do Google; portanto, durante o processo de publicação, será fornecido um link que deve ser aberto em um navegador e conectado ao Google. Posteriormente, as atualizações podem ser publicadas apenas usando a conta em cujo nome a primeira versão foi publicada.


Antes de publicar, é recomendável verificar se a biblioteca está correta usando o flutter packages pub publish --dry-run do flutter packages pub publish --dry-run .


Depois de executar os flutter packages pub publish biblioteca ficará imediatamente disponível no pub.dev. E, como diz a documentação, "A publicação é para sempre" - mais tarde, você só pode enviar novas versões. Versões mais antigas também estarão disponíveis.


Embora a publicação de bibliotecas pareça simples, também pode ter armadilhas. Por exemplo, quando publiquei a primeira versão, obtive alguns pontos na classificação porque a descrição da biblioteca (em pubspec.yaml ) era muito curta.


Você pode ler mais sobre a publicação de bibliotecas aqui .


Na verdade, a biblioteca circular_reveal_animation em pub.dev e github.com .


PS: usei ```java {...} ``` para destacar o código Dart. Seria bom adicionar o código do Dart destacado no habr.com.

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


All Articles