如何在Flutter的PageView中添加进度条动画

How to Add A Progress Bar Animation In PageView in Flutter

我想制作带有进度条的 PageView,它应该是一个带有动画水平线进度条的可滚动页面列表。当用户从一个页面移动到另一个页面时,进度条应该随着动画更新。

它看起来只是像分析工作状态一样显示正在完成的工作状态。进度条将显示为水平条。

这是一个完整的过程和步骤

PageView 小部件的首次设置

import 'package:flutter/material.dart';

class MyPages extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: PageView(
        children: <Widget>[
          Container(
            color: Colors.greenAccent,
            child: Center(child: Text("Page 1"),),
          ),
          Container(
            color: Colors.blueAccent,
            child: Center(child: Text("Page 2"),),
          ),
          Container(
            color: Colors.amberAccent,
            child: Center(child: Text("Page 3"),),
          ),
          Container(
            color: Colors.purpleAccent,
            child: Center(child: Text("Page 4"),),
          ),
        ],
      ),
    );
  }
}

现在添加进度条

我们将在应用的最顶部显示进度条。为此,让我们向 Scaffold 小部件添加一个应用程序栏。

...
Scaffold(
      appBar: AppBar(
        title: Container(
          color: Colors.transparent,
          child: Row(
            children: <Widget>[
              Container(
                  height: 6.0,
                  width: 20.0,
                  decoration: BoxDecoration(
                      color: Colors.white),
                ), 
              Expanded(
                child: Container(
                  height: 6.0,
                  width: double.infinity,
                  decoration: BoxDecoration(
                      color: Colors.cyanAccent),
                ),
              )
            ],
          ),
        ),
      ),
      body: PageView(
...

添加动画、动画控制器和动画小部件

class _MyPagesState extends State<MyPages> with SingleTickerProviderStateMixin{
  Animation<double> _progressAnimation;
  AnimationController _progressAnimcontroller;

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

    _progressAnimcontroller = AnimationController(
      duration: Duration(milliseconds: 200),
      vsync: this,
    );

    _progressAnimation = Tween<double>(begin: 0, end: 0)
    .animate(_progressAnimcontroller);
  }

创建一个名为“AnimatedProgressBar”的 class 来监听进度动画。

class AnimatedProgressBar extends AnimatedWidget {
  AnimatedProgressBar({Key key, Animation<double> animation})
      : super(key: key, listenable: animation);

  Widget build(BuildContext context) {
    final Animation<double> animation = listenable;
    return Container(      
      height: 6.0,
      width: animation.value,
      decoration: BoxDecoration(color: Colors.white),
    );
  }
}

动画进度条

在 initState 事件中调用 _setProgressAnim 函数,然后在 PageView 的 onPageChanged 事件中再次调用。

_setProgressAnim(double maxWidth, int curPageIndex) {
    setState(() {
      growStepWidth = maxWidth / totalPages;
      beginWidth = growStepWidth * (curPageIndex - 1);
      endWidth = growStepWidth * curPageIndex;

      _progressAnimation = Tween<double>(begin: beginWidth, end: endWidth)
          .animate(_progressAnimcontroller);
    });

    _progressAnimcontroller.forward();
  }

最终完整代码

class MyPages extends StatefulWidget {
  @override
  _MyPagesState createState() => _MyPagesState();
}

class _MyPagesState extends State<MyPages> with SingleTickerProviderStateMixin {
  Animation<double> _progressAnimation;
  AnimationController _progressAnimcontroller;

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

    _progressAnimcontroller = AnimationController(
      duration: Duration(milliseconds: 200),
      vsync: this,
    );

    _progressAnimation = Tween<double>(begin: beginWidth, end: endWidth)
        .animate(_progressAnimcontroller);

    _setProgressAnim(0, 1);
  }

  double growStepWidth, beginWidth, endWidth = 0.0;
  int totalPages = 4;

  _setProgressAnim(double maxWidth, int curPageIndex) {
    setState(() {
      growStepWidth = maxWidth / totalPages;
      beginWidth = growStepWidth * (curPageIndex - 1);
      endWidth = growStepWidth * curPageIndex;

      _progressAnimation = Tween<double>(begin: beginWidth, end: endWidth)
          .animate(_progressAnimcontroller);
    });

    _progressAnimcontroller.forward();
  }

  @override
  Widget build(BuildContext context) {
    var mediaQD = MediaQuery.of(context);
    var maxWidth = mediaQD.size.width;

    return Scaffold(
      appBar: AppBar(
        title: Container(
          color: Colors.transparent,
          child: Row(
            children: <Widget>[
              AnimatedProgressBar(
                animation: _progressAnimation,
              ),
              Expanded(
                child: Container(
                  height: 6.0,
                  width: double.infinity,
                  decoration: BoxDecoration(color: Colors.cyanAccent),
                ),
              )
            ],
          ),
        ),
      ),
      body: PageView(
        onPageChanged: (i) {
          //index i starts from 0!
          _progressAnimcontroller.reset(); //reset the animation first
          _setProgressAnim(maxWidth, i + 1);
        },
        children: <Widget>[
          Container(
            color: Colors.greenAccent,
            child: Center(
              child: Text("Page 1"),
            ),
          ),
          Container(
            color: Colors.blueAccent,
            child: Center(
              child: Text("Page 2"),
            ),
          ),
          Container(
            color: Colors.amberAccent,
            child: Center(
              child: Text("Page 3"),
            ),
          ),
          Container(
            color: Colors.purpleAccent,
            child: Center(
              child: Text("Page 4"),
            ),
          ),
        ],
      ),
    );
  }
}

class AnimatedProgressBar extends AnimatedWidget {
  AnimatedProgressBar({Key key, Animation<double> animation})
      : super(key: key, listenable: animation);

  Widget build(BuildContext context) {
    final Animation<double> animation = listenable;
    return Container(
      height: 6.0,
      width: animation.value,
      decoration: BoxDecoration(color: Colors.white),
    );
  }
}

信用和更多信息,请参阅:https://stacksecrets.com/flutter/adding-a-progress-bar-animation-in-page-view