如何在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
我想制作带有进度条的 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