La sensación del latido del corazón de la animación de aleteo.

¡Acostúmbrate a escribir juntos! Este es el primer día de mi participación en el "Nuggets Daily New Plan · April Update Challenge", haz clic para ver los detalles del evento .

Para buscar una mejor experiencia de usuario, a veces necesitamos un control que lata como un latido del corazón para atraer la atención del usuario. Este es un pequeño requisito de optimización, pero en Flutter, la animación de dos piezas apesta como una envoltura de pies. Es larga, por lo que necesita encapsular un AnimatedWidget para liberar la productividad.

implementar animación

混入 SingleTickerProviderStateMixin

Al crear un AnimationController, debe pasar un vsyncparámetro que, cuando esté presente vsync, evitará que la IU animada consuma recursos innecesarios cuando no esté en la pantalla actual. Mezclando en SingleTickerProviderStateMixin.

class _MyHomePageState extends State<MyHomePage>  with SingleTickerProviderStateMixin{}
复制代码

Crear animación

Cree un controlador de animación con un intervalo de casi un segundo:

  late final AnimationController animController;

  @override
  void initState() {
    super.initState();
    animController = AnimationController(
      duration: const Duration(milliseconds: 800),
      vsync: this,
    );
    }
复制代码

La animación de los latidos del corazón es de pequeño a grande y luego a pequeño, por lo que necesita una animación que cambie el tamaño del valor:

  late final Animation<double> animation;

  @override
  void initState() {
    super.initState();
    animController = AnimationController(
      duration: const Duration(milliseconds: 800),
      vsync: this,
    );
     animation = Tween<double>(
      begin: 0.9,
      end: 1.05,
    );
    }

复制代码

El latido del corazón es ininterrumpido, por lo que debe monitorear la animación para reanudarla cuando finalice y luego continuar para iniciar la animación:

    animation = Tween<double>(
      begin: 0.9,
      end: 1.05,
    ).animate(animController)
      ..addListener(() {
        setState(() {});
      })
      ..addStatusListener((status) {
        if (status == AnimationStatus.completed) {
          animController.reverse();
        } else if (status == AnimationStatus.dismissed) {
          animController.forward();
        }
      });
复制代码

Utilice los controles de zoom:

Transform.scale(
                scale: animation.value,
                child: const FlutterLogo(
                  size: 80,
                ),
              ),
复制代码

Simulador de grabación de pantalla - iPhone 13 - 2021-12-07 a las 17.30.50.gif

Para el efecto de salto, resalte la animación de salto y acorte el tiempo de retracción:

   animController = AnimationController(
      reverseDuration: const Duration(milliseconds: 700),
      duration: const Duration(milliseconds: 800),
      vsync: this,
    );
复制代码

Por último, no te olvides de liberar recursos:

  @override
  void dispose() {
    animController.dispose();
    super.dispose();
  }
复制代码

Extraer en pequeños componentes

Para usar una animación similar cada vez que solo necesite importarla, debe separar los componentes de animación y visualización. Cree uno nuevo BounceWidget, incluya animación y luego pase los componentes de la interfaz de usuario:

class BounceWidget extends StatefulWidget {
  final Widget child;

  const BounceWidget({
    Key? key,
    required this.child,
  }) : super(key: key);

  @override
  State<BounceWidget> createState() => _BounceWidgetState();
}
复制代码

Continúe implementando la animación:

class _BounceWidgetState extends State<BounceWidget>
    with SingleTickerProviderStateMixin {
  late Animation<double> animation;
  late AnimationController animController;

  @override
  void initState() {
    super.initState();
    animController = AnimationController(
      reverseDuration: const Duration(milliseconds: 700),
      duration: const Duration(milliseconds: 800),
      vsync: this,
    );
    animation = Tween<double>(
      begin: 0.9,
      end: 1.05,
    ).animate(animController)
      ..addListener(() {
        setState(() {});
      })
      ..addStatusListener((status) {
        if (status == AnimationStatus.completed) {
          animController.reverse();
        } else if (status == AnimationStatus.dismissed) {
          animController.forward();
        }
      });
    animController.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Transform.scale(
      scale: animation.value,
      child: widget.child,
    );
  }

  @override
  void dispose() {
    animController.dispose();
    super.dispose();
  }
}
复制代码

Para importar animación:

  Center(
              child: BounceWidget(
                child: FlutterLogo(
                  size: 80,
                ),
              ),
复制代码

Código completo:

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Padding(
        padding: const EdgeInsets.only(top: 80, left: 16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: const <Widget>[
            Text(
              "心动的",
              style: TextStyle(
                fontSize: 28,
                color: Colors.black,
              ),
            ),
            Text(
              "感觉",
              style: TextStyle(
                fontSize: 48,
                color: Colors.black,
              ),
            ),
            Center(
              child: BounceWidget(
                child: FlutterLogo(
                  size: 80,
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}
复制代码

Supongo que te gusta

Origin juejin.im/post/7083418319159722020
Recomendado
Clasificación