Issue
I want to make the PageView with Progress Bar, which should be a scrollable list of pages with an animated horizontal line progress bar. When the user moves from one page to another, there the progress bar should be updated with the animation.
It just looks like to displays the status of work being done like analyzing the status of work. and a progress bar will be displayed as a horizontal bar.
Solution
Here are a whole process and steps to how can we do it
First Setup Of PageView Widget
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"),),
),
],
),
);
}
}
Now Adding A Progress Bar
We will show the progress bar in the top most section of our app. Let’s add an application bar to the Scaffold widget for this purpose.
...
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(
...
Add The Animation, Animation Controller And Animated Widget
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);
}
Create a class called “AnimatedProgressBar” that will listen to the progress animation.
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),
);
}
}
Animating The Progress Bar
Call the _setProgressAnim function on the initState event and then again during the onPageChanged event of the PageView.
_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();
}
final Full code
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),
);
}
}
Credit and For more info, see: https://stacksecrets.com/flutter/adding-a-progress-bar-animation-in-page-view
Answered By – Paresh Mangukiya
Answer Checked By – Robin (FlutterFixes Admin)