Search code examples
androidflutteranimationprogress-bar

How to progress smoothly LinearProgressIndicator


So I'm trying to create a linear progress indicator in Flutter, that over 5 seconds, smoothly fill in the indicator. Currently my approach is the following:

import 'dart:async';

import 'package:flutter/material.dart';

class MyFile extends StatefulWidget {
  const MyFile({super.key});

  @override
  State<MyFile> createState() => _MyFileState();
}

class _MyFileState extends State<MyFile> {
  double _value = 0.0;

  @override
  void initState() {
    super.initState();

    Timer.periodic(const Duration(seconds: 1), (timer) {
      setState(() {
        _value += .2;
      });

      if (_value == 1) {
        timer.cancel();
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: LinearProgressIndicator(
          value: _value,
        ),
      ),
    );
  }
}

This works but the progress is shown in steps rather than smoothly filling the progress indicator. Is there any way I can accomplish that? Thank you


Solution

  • To create a smooth LinearProgressIndicator gradually fills over a period of time, you can use the

    AnimationController and TweenAnimationBuilder

    for more precise and smooth animation.

    import 'package:flutter/material.dart';
    
    class MyFile extends StatefulWidget {
      const MyFile({super.key});
    
      @override
      State<MyFile> createState() => _MyFileState();
    }
    
    class _MyFileState extends State<MyFile> with SingleTickerProviderStateMixin {
      late AnimationController _controller;
    
      @override
      void initState() {
        super.initState();
    
        // Initialize the AnimationController
        _controller = AnimationController(
          vsync: this,
          duration: const Duration(seconds: 5), // total duration for the progress
        )..forward(); // start the animation immediately
      }
    
      @override
      void dispose() {
        _controller.dispose(); // Always dispose of the controller when not needed
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: SafeArea(
            child: Center(
              child: AnimatedBuilder(
                animation: _controller,
                builder: (context, child) {
                  return LinearProgressIndicator(
                    value: _controller.value, // This value changes smoothly over time
                  );
                },
              ),
            ),
          ),
        );
      }
    }
    

    AnimationController

    : We use this to control the animation. It smoothly changes its value from 0.0 to 1.0 over a period of time, which you specify (in this case, 5 seconds).

    forward()

    : This starts the animation immediately after the controller is created.

    AnimatedBuilder

    : This widget rebuilds the LinearProgressIndicator whenever the animation's value changes, providing a smooth transition.

    dispose()

    : We make sure to dispose of the AnimationController when it's no longer needed to prevent memory leaks.