πŸ”₯#10FlutterChallenges - Part 1: progress bar with gradient

Real scenarios & real problems. Learn how to make an custom progress bar with the gradient background that will looks tasty!

πŸ”₯#10FlutterChallenges - Part 1: progress bar with gradient
Photo by Ash Edmonds / Unsplash

Series Intro πŸ‘‹

Welcome to the #10FlutterChallenges series, where I'll show you how to build some real features built in Flutter.

In this series of blog posts, I show you 10 features with the tricky parts and a code solution build from scratch.

So let's get started!

Part 1:

In this part we want to build a simple progress bar that has a label that will display the current value and the maximum value after / like that: 100/1000.

Issue #1 – progress bar

In order for this to work, we are going to need the following widgets provided by Flutter:

Below I prepared a ready code for the progress bar based on the above classes and adding a bit of style:

import 'package:flutter/material.dart';

class CustomProgressBar extends StatelessWidget {
  const CustomProgressBar({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        SizedBox(
          width: MediaQuery.of(context).size.width,
          height: 20,
          child: const LinearProgressIndicator(
            backgroundColor: Color(0xff323232),
            valueColor: AlwaysStoppedAnimation<Color>(
              Color(0xFF21bf73),
            ),
            value: 0.5,
          ),
        ),
        const Positioned.fill(
          child: Align(
            alignment: Alignment.center,
            child: Text(
              '200/1000',
              style: TextStyle(
                color: Colors.white,
                fontSize: 10,
                fontFamily: 'RetroGaming',
                fontWeight: FontWeight.bold,
              ),
            ),
          ),
        )
      ],
    );
  }
}

NOTE: It is important to pass value as a double integer in the range 0 - 1. The LinearProgressIndicator takes this value and it is converted as a percentage of the progress e.g. 0.2 = 20%.

Remember: you need to wrap the progress bar in Expanded class where you invoke it to prevent RenderBox exception.

As you have probably noticed, many values ​​can be passed from outside as arguments to this widget, e.g., colors, height etc. I encourage you to make it more general.

Okay, our progress bar looks fine, let's move on to the slightly more difficult part.

Issue #2 – candy cane 🍭

Do you know how a candy cane looks like? If not, here's the picture:

Photo by lilartsy / Unsplash

Yes, I know it tastes great too 😊, but it's not a culinary blog. The point is, we want the background of the progress bar to look like the texture of this candy.

Step 1: Create background

First, we need to replace the previously created SizedBox inside the Stack with a Container with additional styles. That will be our background bar where we will put the gradient:

Container(
          width: MediaQuery.of(context).size.width,
          height: 20,
          decoration: BoxDecoration(
            border: Border.all(
              color: Colors.grey.shade200,
            ),
            color: Colors.white70,
          ),
        ),

Step 2: Add gradient

The next thing to do is simply add another Container over the current one. We can achieve this thanks to the Stack widget. To do this, we need to add this new Container after the first one:

Container(
          width: MediaQuery.of(context).size.width - 100,
          height: 20,
          decoration: const BoxDecoration(
            gradient: LinearGradient(
              begin: Alignment(-0.75, -1.1),
              end: Alignment(-0.6, 0),
              stops: [0.0, 0.5, 0.5, 1],
              colors: [
                Colors.red,
                Colors.red,
                Colors.white,
                Colors.white,
              ],
              tileMode: TileMode.mirror,
            ),
          ),
        ),

Let's describe the important parts of this code:

  • The Width factor is, for simplicity, reduced by 100 from the full width of the device (this should be replaced with some dynamic value such as %)
  • Next comes the LinearGradient class, in which we define properties suited to our needs, such as steps, alignments, and colors array
  • The last thing is the tileMode property which is responsible for:
How this gradient should tile the plane beyond in the region before [begin] and after [end].

And the value of the mirror will be just right to create our candy-cane gradient

SUMMARY:

That's it 😎 Our candy-cane progress bar looks delicious. The label may remain unchanged. You can always check out the full source code below:

This is the source code of the Flutter Challenges series post: https://fun4code.com/15FlutterChallanges-part1/
This is the source code of the Flutter Challenges series post: https://fun4code.com/15FlutterChallanges-part1/ - candy_cane_progress_bar.dart

What’s next?

And that's all for this challenge ✌️

In this post, I went over the build and customized progress bar using the built-in Flutter widgets and showed some customization possibilities.

In the next, we will build a toggle button, also with no external libraries.


Thanks for reading β™₯️β™₯️

…and stay tuned! πŸ‘Š

Also check out the rest of the Flutter Challenges:

Part 1 β€” #10FlutterChallenges - Part 1: progress bar with gradient
Part 2 β€” #10FlutterChallenges - Part 2: switch button
Part 3 β€” #10FlutterChallenges - Part 3: Audio + LifeCycle service