【问题标题】:SOLVED How to trigger animation on widget rebuild?已解决如何在小部件重建时触发动画?
【发布时间】:2022-08-07 16:31:09
【问题描述】:

我将按此顺序描述我的应用程序正在做什么、我想要实现什么以及我尝试过什么。

我有一个应用程序,其中一个屏幕,我们称之为FooScreen,包含一些小部件,但主要显示图像。用户可以点击一个按钮来显示以下图像。这种更改图像的功能由Provider 处理 - 当用户点击按钮时,currentAssetName 会更改并通知听众。正因为如此,整个屏幕并没有重建,只有负责显示图像的小部件,我们称之为FooImage

class FooScreen extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Column(
       ...Some widgets
       FooImage()
       ....
    );
  }
}
class FooImage extends StatelessWidget {
  const FooImage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final fooProvider = context.watch<FooProvider>();
    final assetName = fooProvider.assetName;
    return Image.asset(assetname);
  }
}

目前,当资产名称更改并渲染新图像时,它会在屏幕上显示难看的闪光灯。我希望此图像在更改时具有动画效果。

我试图创建一个包装小部件,我们称之为FooWrapper,我在initState() 上创建动画并将其传递给FooImage

class FooWrapper extends StatefulWidget {

  @override
  State<FooWrapper> createState() => _FooWrapperState();
}

class _FooWrapperState extends State<FooWrapper> 
   with SingleTickerProviderStateMixin {

  late Animation<double> animation;
  late AnimationController controller;

  @override
  void initState() {
    super.initState();
    controller = AnimationController(
        duration: const Duration(milliseconds: 500), vsync: this);
    animation = Tween<double>(begin: 0, end: 600).animate(controller);
    controller.forward();
  }
 
  @override
  void dispose() {
    // I am aware that disposing `late` variable ain\'t smartest thing to do,
    //  I will change it when I will make it work 
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return FooImage(animation: animation)
  }
}

可以看出,FooImage 变了

class FooImage extends AnimatedWidget {
  const FooImage(super.key, required Animation<double> animation) : super(listenable: animation);

  @override
  Widget build(BuildContext context) {
    final fooProvider = context.watch<FooProvider>();
    final assetName = fooProvider.assetName;
    final animation = listenable as Animation<double>;

    return Image.asset(
      height: animation.value,
      width: animation.value,
      assetName,
    );
  }
}

现在,它仅在第一次渲染FooScreen 时才有效,当我更改图像时它仍然只闪烁。我尝试了一些体操来使它起作用,但没有结果。我将不胜感激有关如何处理它的任何提示

    标签: android ios flutter dart


    【解决方案1】:

    我让它工作了,但我几乎可以肯定这不是处理它的最佳方法。

    我在FooWrapper 中观看fooProvider,并将其作为参数传递给FooImage。我还将SingleTickerProviderStateMixin 更改为TickerProviderStateMixin,并将控制器和动画定义移动到didChangeDependencies(),以便在每次重建之前触发它。

    class FooWrapper extends StatefulWidget {
    
      @override
      State<FooWrapper> createState() => _FooWrapperState();
    }
    
    class _FooWrapperState extends State<FooWrapper> 
       with TickerProviderStateMixin {
    
      late Animation<double> animation;
      late AnimationController controller;
    
      @override
      void initState() {
        super.initState();
      }
    
      @override
      void didChangeDependencies() {
        controller = AnimationController(
            duration: const Duration(milliseconds: 300), vsync: this);
        animation = Tween<double>(begin: 0, end: 600).animate(controller);
        controller.forward();
        super.didChangeDependencies();
      }
     
      @override
      void dispose() {
        // I am aware that disposing `late` variable ain't smartest thing to do,
        //  I will change it when I will make it work 
        controller.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        final fooProvider = context.watch<FooProvider>();
        return FooImage(fooProvider, animation: animation)
      }
    }
    
    class FooImage extends AnimatedWidget {
      const FooImage(this.fooProvider, super.key, required Animation<double> animation) : super(listenable: animation);
    
      final FooProvider fooProvider;
    
      @override
      Widget build(BuildContext context) {
        final assetName = fooProvider.assetName;
        final animation = listenable as Animation<double>;
    
        return Image.asset(
          height: animation.value,
          width: animation.value,
          assetName,
        );
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-16
      • 2019-07-25
      • 2020-09-12
      • 2012-04-04
      • 1970-01-01
      • 1970-01-01
      • 2019-01-03
      • 1970-01-01
      相关资源
      最近更新 更多