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

Flutter 如何在Flatter中的PageView中添加进度条动画,flutter,dart,progress-bar,pageviews,flutter-pageview,Flutter,Dart,Progress Bar,Pageviews,Flutter Pageview,我想制作带有进度条的页面视图,它应该是一个带有动画水平线进度条的可滚动页面列表。当用户从一个页面移动到另一个页面时,应使用动画更新进度条 class AnimatedProgressBar extends AnimatedWidget { AnimatedProgressBar({Key key, Animation<double> animation}) : super(key: key, listenable: animation); Widget buil

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

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),
    );
  }
}

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

以下是我们如何完成的整个过程和步骤

首次设置页面视图小部件

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"),),
          ),
        ],
      ),
    );
  }
}
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);
  }
导入“包装:颤振/材料.省道”;
类MyPages扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回脚手架(
正文:页面视图(
儿童:[
容器(
颜色:Colors.greenAccent,
子:居中(子:文本(“第1页”),
),
容器(
颜色:Colors.blueAccent,
子:居中(子:文本(“第2页”),
),
容器(
颜色:Colors.amberAccent,
子:居中(子:文本(“第3页”),
),
容器(
颜色:颜色。紫红色,
子:居中(子:文本(“第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(
...
。。。
脚手架(
appBar:appBar(
标题:集装箱(
颜色:颜色。透明,
孩子:排(
儿童:[
容器(
身高:6.0,
宽度:20.0,
装饰:盒子装饰(
颜色:颜色。白色),
), 
扩大(
子:容器(
身高:6.0,
宽度:double.infinity,
装饰:盒子装饰(
颜色:颜色。青色强调),
),
)
],
),
),
),
正文:页面视图(
...
添加动画、动画控制器和动画小部件

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"),),
          ),
        ],
      ),
    );
  }
}
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);
  }
class\u MyPagesState使用SingleTickerProviderStateMixin扩展状态{
动画(动画);;
AnimationController _ProgressAnimationController;
@凌驾
void initState(){
super.initState();
_progressAnimcontroller=AnimationController(
持续时间:持续时间(毫秒:200),
vsync:这个,,
);
_progressAnimation=Tween(开始:0,结束:0)
.设置动画(_progressAnimcontroller);
}
创建一个名为“AnimatedProgressBar”的类,该类将侦听进度动画

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),
    );
  }
}
class AnimatedProgressBar扩展AnimatedWidget{
AnimatedProgressBar({Key,Animation Animation})
:super(关键点:关键点,可收听:动画);
小部件构建(构建上下文){
最终动画=可收听;
退回货柜(
身高:6.0,
宽度:animation.value,
装饰:盒子装饰(颜色:彩色。白色),
);
}
}
设置进度条动画

在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();
  }
\u setProgressAnim(双maxWidth,int curPageIndex){
设置状态(){
GrowthStepWidth=maxWidth/totalPages;
beginWidth=GrowthStepWidth*(curPageIndex-1);
endWidth=growtStepWidth*curPageIndex;
_progressAnimation=Tween(开始:beginWidth,结束:endWidth)
.设置动画(_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),
    );
  }
}
类MyPages扩展StatefulWidget{
@凌驾
_MyPagesState createState()=>\u MyPagesState();
}
类_MyPagesState使用SingleTickerProviderStateMixin扩展状态{
动画(动画);;
AnimationController _ProgressAnimationController;
@凌驾
void initState(){
super.initState();
_progressAnimcontroller=AnimationController(
持续时间:持续时间(毫秒:200),
vsync:这个,,
);
_progressAnimation=Tween(开始:beginWidth,结束:endWidth)
.设置动画(_progressAnimcontroller);
_setProgressAnim(0,1);
}
双增长步长,起始宽度,终止宽度=0.0;
int totalPages=4;
_setProgressAnim(双maxWidth,int curPageIndex){
设置状态(){
GrowthStepWidth=maxWidth/totalPages;
beginWidth=GrowthStepWidth*(curPageIndex-1);
endWidth=growtStepWidth*curPageIndex;
_progressAnimation=Tween(开始:beginWidth,结束:endWidth)
.设置动画(_progressAnimcontroller);
});
_progressAnimcontroller.forward();
}
@凌驾
小部件构建(构建上下文){
var mediaQD=MediaQuery.of(上下文);
var maxWidth=mediaQD.size.width;
返回脚手架(
appBar:appBar(
标题:集装箱(
颜色:颜色。透明,
孩子:排(
儿童:[
动画进度条(
动画:_progressAnimation,
),
扩大(
子:容器(
身高:6.0,
宽度:double.infinity,
装饰:盒子装饰(颜色:Colors.cyanAccent),
),
)
],
),
),
),
正文:页面视图(
更改网页:(i){
//索引i从0开始!
_progressAnimcontroller.reset();//首先重置动画
_setProgressAnim(最大宽度,i+1);
},
儿童:[
容器(
颜色:Colors.greenAccent,
儿童:中心(
子项:文本(“第1页”),
),
),
容器(
颜色:Colors.blueAccent,