How to Add A Progress Bar Animation In PageView in Flutter

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

enter image description here

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)

Leave a Reply

Your email address will not be published. Required fields are marked *