扑如何让 AnimationBuilder 听多个动画?

问题描述

class _SomeWidgetWithAnimationsstate extends State<SomeWidgetWithAnimations> with TickerProviderStateMixin {
  AnimationController firstController;
  AnimationController secondController;

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
        aniamtion: /* Here I want to pass the two animation controllers above */,builder: (context,child) => /* Something that uses two animations to animate */,);
  }
}

我希望能够侦听来自多个 Listenable 的事件,其中只需要一个 Listenable。有没有办法将通知从两个 Listenable 路由到一个?我考虑过创建自己的 Listenable 实现,该实现将具有一些方法,例如 addSourceListenable(Listenable source),该方法将通过回调订阅 Listenable 源,该回调将通知其自己的订阅者。但我认为有一个更优雅的方法解决这个问题。也许 RxDart 可以提供一些东西。

解决方法

对于具有多个动画的用例,flutter 有一个自己的概念,称为 Staggered Animations。您可以在此处阅读更多相关信息:

https://flutter.dev/docs/development/ui/animations/staggered-animations#:~:text=To%20create%20a%20staggered%20animation,being%20animated%2C%20create%20a%20Tween%20

这是文章中提供的完整工作示例:

// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart' show timeDilation;

class StaggerAnimation extends StatelessWidget {
  StaggerAnimation({ Key key,this.controller }) :

    // Each animation defined here transforms its value during the subset
    // of the controller's duration defined by the animation's interval.
    // For example the opacity animation transforms its value during
    // the first 10% of the controller's duration.

    opacity = Tween<double>(
      begin: 0.0,end: 1.0,).animate(
      CurvedAnimation(
        parent: controller,curve: Interval(
          0.0,0.100,curve: Curves.ease,),width = Tween<double>(
      begin: 50.0,end: 150.0,curve: Interval(
          0.125,0.250,height = Tween<double>(
      begin: 50.0,end: 150.0
    ).animate(
      CurvedAnimation(
        parent: controller,curve: Interval(
          0.250,0.375,padding = EdgeInsetsTween(
      begin: const EdgeInsets.only(bottom: 16.0),end: const EdgeInsets.only(bottom: 75.0),borderRadius = BorderRadiusTween(
      begin: BorderRadius.circular(4.0),end: BorderRadius.circular(75.0),curve: Interval(
          0.375,0.500,color = ColorTween(
      begin: Colors.indigo[100],end: Colors.orange[400],curve: Interval(
          0.500,0.750,super(key: key);

  final Animation<double> controller;
  final Animation<double> opacity;
  final Animation<double> width;
  final Animation<double> height;
  final Animation<EdgeInsets> padding;
  final Animation<BorderRadius> borderRadius;
  final Animation<Color> color;

  // This function is called each time the controller "ticks" a new frame.
  // When it runs,all of the animation's values will have been
  // updated to reflect the controller's current value.
  Widget _buildAnimation(BuildContext context,Widget child) {
    return Container(
      padding: padding.value,alignment: Alignment.bottomCenter,child: Opacity(
        opacity: opacity.value,child: Container(
          width: width.value,height: height.value,decoration: BoxDecoration(
            color: color.value,border: Border.all(
              color: Colors.indigo[300],width: 3.0,borderRadius: borderRadius.value,);
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      builder: _buildAnimation,animation: controller,);
  }
}

class StaggerDemo extends StatefulWidget {
  @override
  _StaggerDemoState createState() => _StaggerDemoState();
}

class _StaggerDemoState extends State<StaggerDemo> with TickerProviderStateMixin {
  AnimationController _controller;

  @override
  void initState() {
    super.initState();

    _controller = AnimationController(
      duration: const Duration(milliseconds: 2000),vsync: this
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  Future<void> _playAnimation() async {
    try {
      await _controller.forward().orCancel;
      await _controller.reverse().orCancel;
    } on TickerCanceled {
      // the animation got canceled,probably because we were disposed
    }
  }

  @override
  Widget build(BuildContext context) {
    timeDilation = 10.0; // 1.0 is normal animation speed.
    return Scaffold(
      appBar: AppBar(
        title: const Text('Staggered Animation'),body: GestureDetector(
        behavior: HitTestBehavior.opaque,onTap: () {
          _playAnimation();
        },child: Center(
          child: Container(
            width: 300.0,height: 300.0,decoration: BoxDecoration(
              color: Colors.black.withOpacity(0.1),border: Border.all(
                color:  Colors.black.withOpacity(0.5),child: StaggerAnimation(
              controller: _controller.view
            ),);
  }
}

void main() {
  runApp(MaterialApp(home: StaggerDemo()));
}

您几乎可以做任何事情,并且将其链接在逻辑中。我建议你只是指导将文档扔到那里,它的解释很好。

,

看看 Listenable.merge(List<Listenable?> listenables),它返回一个当任何给定的 Listenable 本身触发时触发的 Listenable。 希望我对你有帮助:)

https://api.flutter.dev/flutter/foundation/Listenable/Listenable.merge.html

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...