flutter - Flutter中如何在PageView中添加进度条动画
问题描述
我想制作带有进度条的 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 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
推荐阅读
- java - 如何制作一个支持显示剪切的应用程序?- 安卓Java
- java - 原因:java.lang.InternalError: Can't connect to X11 window server using 'host:10.0' as the value of the DISPLAY variable
- r - 我可以在 mgcv::gam.plot() 中解释我的 y 轴的“系数”吗?
- macos - 在 Big Sur 上未找到 Xilinx Ultrascale UART
- reactjs - REACT GET 请求两次获取基本 URL
- java - org.apache.hc.core5.http2.impl.nio.AbstractH2StreamMultiplexer.onInput 中的 java.nio.BufferOverflowException
- r - R中的后向差异和中心差异
- python - 中断后如何恢复训练 pl.Trainer?
- html - 带有 CSS SVG 背景图像的按钮不会显示在 Safari/Webkit IOS 或 MacOS 上
- ruby-on-rails - Rails ActionMailer - 防止电子邮件传递以进行测试