Flutter – Animación de héroe radial

Una transformación radial significa convertir una forma circular en una forma cuadrada. En la animación Radial Hero se hace lo mismo con un Hero. En Flutter, se usa un widget de héroe para crear una animación de héroe. Un héroe en este contexto se refiere a un widget que se mueve entre pantallas. Este es uno de los tipos de animación más fundamentales utilizados en la aplicación, especialmente si la aplicación trata con medios como imágenes. En pocas palabras, una animación de héroe es cuando un héroe vuela de una pantalla a otra.

El siguiente proceso ocurre al crear una animación de héroe radial:

  • El widget RadialExpansion se usa para envolver al héroe.
  • El tamaño del héroe cambia a medida que vuela por las rutas y el héroe adopta el tamaño del niño.
  • Dos clips superpuestos forman la animación RadialExpansion.
  • El PageRouteBuilder se usa para construir el destino del héroe.
  • Todos los gestos son manejados por el widget InkWell.

La siguiente imagen muestra la transformación radial de un héroe en el tiempo = 0 al tiempo = 1.

Afterclipping

El widget RadialExpansion funciona de la siguiente manera representada:

Ahora construyamos una aplicación simple que tenga tres héroes que hagan una transformación radial cuando se haga clic en ellos. Los héroes se almacenarán en la siguiente carpeta de la aplicación flutter:

flutter_app/assets/images/.....

Asegúrate de agregar las dependencias en el archivo pubspec.yaml como se muestra a continuación:

Ahora construyamos el archivo main.dart :

Dart

import 'dart:math' as math;
  
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart' show timeDilation;
  
class Photo extends StatelessWidget {
  Photo({ Key key, this.photo, this.color, this.onTap }) : super(key: key);
  
  final String photo;
  final Color color;
  final VoidCallback onTap;
  
  Widget build(BuildContext context) {
    return Material(
      color: Theme.of(context).primaryColor.withOpacity(0.25),
      child: InkWell(
        onTap: onTap,
        child: LayoutBuilder(
          builder: (BuildContext context, BoxConstraints size) {
            return Image.asset(
              photo,
              fit: BoxFit.contain,
            );
          },
        ),
      ),
    );
  }
}
  
class RadialExpansion extends StatelessWidget {
  RadialExpansion({
    Key key,
    this.maxRadius,
    this.child,
  }) : clipRectSize = 2.0 * (maxRadius / math.sqrt2),
        super(key: key);
  
  final double maxRadius;
  final clipRectSize;
  final Widget child;
  
  @override
  Widget build(BuildContext context) {
    return ClipOval(
      child: Center(
        child: SizedBox(
          width: clipRectSize,
          height: clipRectSize,
          child: ClipRect(
            child: child,
          ),
        ),
      ),
    );
  }
}
  
class RadialExpansionDemo extends StatelessWidget {
  static const double kMinRadius = 32.0;
  static const double kMaxRadius = 128.0;
  static const opacityCurve = const Interval(0.0, 0.75, curve: Curves.fastOutSlowIn);
  
  static RectTween _createRectTween(Rect begin, Rect end) {
    return MaterialRectCenterArcTween(begin: begin, end: end);
  }
  
  static Widget _buildPage(BuildContext context, String imageName, String description) {
    return Container(
      color: Theme.of(context).canvasColor,
      child: Center(
        child: Card(
          elevation: 8.0,
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              SizedBox(
                width: kMaxRadius * 2.0,
                height: kMaxRadius * 2.0,
                child: Hero(
                  createRectTween: _createRectTween,
                  tag: imageName,
                  child: RadialExpansion(
                    maxRadius: kMaxRadius,
                    child: Photo(
                      photo: imageName,
                      onTap: () {
                        Navigator.of(context).pop();
                      },
                    ),
                  ),
                ),
              ),
              Text(
                description,
                style: TextStyle(fontWeight: FontWeight.bold),
                textScaleFactor: 3.0,
              ),
              const SizedBox(height: 20.0),
            ],
          ),
        ),
      ),
    );
  }
  
  Widget _buildHero(BuildContext context, String imageName, String description) {
    return Container(
      width: kMinRadius * 3.0,
      height: kMinRadius * 3.0,
      child: Hero(
        createRectTween: _createRectTween,
        tag: imageName,
        child: RadialExpansion(
          maxRadius: kMaxRadius,
          child: Photo(
            photo: imageName,
            onTap: () {
              Navigator.of(context).push(
                PageRouteBuilder<void>(
                  pageBuilder: (BuildContext context,
                                Animation<double> animation,
                                Animation<double> secondaryAnimation) {
                    return AnimatedBuilder(
                        animation: animation,
                        builder: (BuildContext context, Widget child) {
                          return Opacity(
                            opacity: opacityCurve.transform(animation.value),
                            child: _buildPage(context, imageName, description,),
  
                          );
                        }
                    );
                  },
                ),
              );
            },
          ),
        ),
      ),
    );
  }
  
  @override
  Widget build(BuildContext context) {
    // animation speed.
    timeDilation = 4.0;
  
    return Scaffold(
      appBar: AppBar(
        title: const Text('GeeksForGeeks'),
        backgroundColor: Colors.green,
      ),
      body: Container(
        padding: const EdgeInsets.all(33.0),
        alignment: FractionalOffset.bottomLeft,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            _buildHero(context, 'assets/images/aquaman.png', 'Aquaman'),
            _buildHero(context, 'assets/images/superman.jpg', 'Superman'),
            _buildHero(context, 'assets/images/wonderwomen.jpg', 'Wonderwomen'),
          ],
        ),
      ),
    );
  }
}
  
void main() {
  runApp(MaterialApp(home: RadialExpansionDemo()));
}

Producción:

Publicación traducida automáticamente

Artículo escrito por ddeevviissaavviittaa y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *