如何将自定义动画作为 Flutter 进度/加载指示器?

Posted

技术标签:

【中文标题】如何将自定义动画作为 Flutter 进度/加载指示器?【英文标题】:How to have a custom animation as a Flutter progress / loading indicator? 【发布时间】:2020-07-12 17:48:46 【问题描述】:

我正在尝试用我自己的动画替换默认的 CircularProgressIndicator。我根据How to rotate an image using Flutter AnimationController and Transform? 此处的示例创建了一个旋转小部件,但是当用“MyIconSpinner”替换 CircularProgressIndicator 时,由于某种原因它没有出现。请问有什么提示吗? 这是MyIconSpinner的内容

import 'package:flutter/material.dart';
import 'package:flutter_icons/flutter_icons.dart';

class MyIconSpinner extends StatefulWidget 
  MyIconSpinner(Key key, this.title) : super(key: key);

  final String title;

  @override
  _MyIconSpinnerState createState() => _MyIconSpinnerState();


class _MyIconSpinnerState extends State<MyIconSpinner>
    with TickerProviderStateMixin 
  AnimationController _controller;

  @override
  void initState() 
    _controller = AnimationController(
      duration: const Duration(milliseconds: 5000),
      vsync: this,
    );
    super.initState();
  

  @override
  Widget build(BuildContext context) 
    _controller.forward();

    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            RotationTransition(
              turns: Tween(begin: 0.0, end: 1.0).animate(_controller),
              child: Icon(
                Icons.star,
                size: 40,
              ),
            ),
          ],
        ),
      ),
    );
  

我将它放在这样的小部件中

return Scaffold(
    appBar: AppBar(
      title: Text("Appbar"),
      backgroundColor: Colors.black,
      automaticallyImplyLeading: false,
    ),
    body: Center(
        child: Column(children: <Widget>[
        StreamBuilder(
            stream: doSomething(withSomeData),
            builder: (BuildContext context,
                AsyncSnapshot<List<DocumentSnapshot>> asyncSnapshot) 
             if (!asyncSnapshot.hasData) return MyIconSpinner();

【问题讨论】:

【参考方案1】:

我认为你不应该将MyIconSpinner 包裹在Scaffold 中。您应该提供MyIconSpinner 颜色参数,并在完成后重复动画。这是MyIconSpinner的编辑版本。

class MyIconSpinner extends StatefulWidget 
  MyIconSpinner(Key key, this.title, this.color = Colors.blue) : super(key: key);

  final String title;
  final Color color; 

  @override
  _MyIconSpinnerState createState() => _MyIconSpinnerState();


class _MyIconSpinnerState extends State<MyIconSpinner>
    with TickerProviderStateMixin 
  AnimationController _controller;

  @override
  void initState() 
    _controller = AnimationController(
      duration: const Duration(milliseconds: 5000),
      vsync: this,
    );

    _controller.addListener(()
      if(_controller.isCompleted)
        _controller.repeat();
      
    );

    super.initState();
  

  @override
  Widget build(BuildContext context) 
    _controller.forward();
    return RotationTransition(
      turns: Tween(begin: 0.0, end: 1.0).animate(_controller),
      child: Icon(
        Icons.star,
        size: 40,
        color: widget.color,
      ),
    );
  

【讨论】:

谢谢!只是测试它。收到错误“_MyIconSpinnerState#d514e(tickers: tracking 1 ticker) was disposed with an active Ticker.” @giorgio79 我测试过,效果很好。我无法弄清楚为什么在没有上下文的情况下会出现此错误。您可以尝试在 dispose 方法上添加_controller.dispose() 它有效,谢谢!问题出在我的 FutureBuilder 的上游!

以上是关于如何将自定义动画作为 Flutter 进度/加载指示器?的主要内容,如果未能解决你的问题,请参考以下文章

如何将自定义视图动画化为自定义视图

如何使用 Materialise 线性不确定进度条作为页面预加载器?

如何将自定义动画添加到 ContextMenuStrip?

canvas动画之一 -- 百分比进度加载

Flutter Spinkit 进度指示器

将自定义 boxshadow 添加到 Flutter 卡