Home > other >  Flutter - Container with ring progress indicator border
Flutter - Container with ring progress indicator border

Time:11-20

I am trying to achieve a container that will have a progress indicator border, like in this image:

Image

I've tried to achieve it using a container inside another container (1 container for the outside white border, and one container for the inside blue background with the icon), but I can't achieve the progress indicator effect.

Does anyone know how can I achieve this?

Thank you

CodePudding user response:

If you don't want to use a CustomPainter you can try to achieve that with a Stack widget

You can see this example in DartPad

Use the value property on the second CircularProgressIndicator to update the value with setState or any other State Management technique you like

import 'package:flutter/material.dart';

const Color darkBlue = Color.fromARGB(255, 18, 32, 47);

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(
        scaffoldBackgroundColor: darkBlue,
      ),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: MyWidget(),
        ),
      ),
    );
  }
}

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: const [
        CircleAvatar(
          backgroundColor: Colors.white,
          radius: 24,
          child: Icon(Icons.check),
        ),
        SizedBox(
          width: 50,
          height: 50,
          child: CircularProgressIndicator(
            color: Colors.grey,
            value: 1,
          ),
        ),
        SizedBox(
          width: 50,
          height: 50,
          child: CircularProgressIndicator(
            color: Colors.blue,
            value: .3, // Change this value to update the progress
          ),
        ),
      ],
    );
  }
}

CodePudding user response:

There is a widget called CircularProgressIndicator that seems to be exactly what you're after.

How to use it:

CircularProgressIndicator(
              backgroundColor: Colors.white, 
              color: Colors.purple.withAlpha(100), 
              strokeWidth: 5,
              value: value, //
            ),

backgroundColor: for the white background

color: for the purple overlay

strokeWidth: for the thickness that you want

value the actual progress of the indicator

And to have the arrow on top just use a round white Container (use a BoxDecoration with shape: BoxShape.circle to make it a circle), and put the arrow on top of it using the Stack widget.

Hopes this helps!

CodePudding user response:


class ProgressPainter extends CustomPainter {
  final double value;
  double deg2rad(double deg) => deg * pi / 180;
  ProgressPainter({
    required this.value,
  });

  @override
  void paint(Canvas canvas, Size size) {
    Paint paint = Paint()..color = Colors.blueGrey;

    final rect = Rect.fromCenter(
        center: Offset(size.height / 2, size.width / 2),
        width: size.width,
        height: size.height);

    canvas.drawArc(
        rect,
        deg2rad(-90),
        deg2rad(
          (value * 360) / 100, // % to degree
        ),
        true,
        paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return false;
  }
}

And use

      CustomPaint(
                  painter: ProgressPainter(value: sliderVal),
                  child: const SizedBox(
                    height: 100,
                    width: 100,
                    child: Icon( // your inner widget
                      Icons.ac_unit,
                      size: 100,
                    ),
                  ),
                ),

Tested widget:


class _MyHomePageState extends State<MyHomePage> {
  double sliderVal = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(widget.title)),
      body: Center(
        child: Column(
          children: [
            CustomPaint(
              painter: ProgressPainter(value: sliderVal),
              child: const SizedBox(
                height: 100,
                width: 100,
                child: Icon(
                  Icons.ac_unit,
                  size: 100,
                ),
              ),
            ),
            Slider(
              value: sliderVal,
              min: 0,
              max: 100,
              onChanged: (value) {
                setState(() {
                  sliderVal = value;
                });
              },
            )
          ],
        ),
      ),
    );
  }
}
  • Related