Placing text in the center of a CircularProgressIndicator
Asked Answered
B

6

8

I'm trying to place a text countdown timer in the center of a CircularProgressIndicator. This is the code for the layout of the body:

return new Column(
  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  children: <Widget>[
    Stack(
      children: <Widget>[
        Container(
          width: 200,
          height: 200,
          child: new CircularProgressIndicator(
            strokeWidth: 15,
            value: value,
          ),
        ),
        Align(
          alignment: FractionalOffset.center,
          child: Text("Test")
        )
      ],
    ),
    ...
  ],
);

Adding the Align() widget changes the layout from this: Before

to this: After

I've also tried

Align(
  alignment: Alignment.center,
  child: Text("Test")
)

and

Center(
  child: Text("Test"),
)

instead of the Align() widget, but they all produce the same result

Bertolde answered 10/12, 2018 at 17:20 Comment(0)
U
11

That's because your Stack doesn't have size, in order to fix your issue, wrap your Stack inside SizedBox, set a height, and Center the Text.

Column(
  children: <Widget>[
    SizedBox(
      height: 200.0,
      child: Stack(
        children: <Widget>[
          Center(
            child: Container(
              width: 200,
              height: 200,
              child: new CircularProgressIndicator(
                strokeWidth: 15,
                value: 1.0,
              ),
            ),
          ),
          Center(child: Text("Test")),
        ],
      ),
    ),
  ],
)
Urbanity answered 10/12, 2018 at 17:34 Comment(0)
H
2

Correct version of circular progress bar with text inside (2023, Flutter 3.16.0)

enter image description here

  Widget _circularProgressWithText({required int percentage, String? text}) {
    var value = percentage / 100.0;
    var size = 42.0;
    
    text ??= '$percentage%';

    return Stack(
      alignment: AlignmentDirectional.center,
      children: <Widget>[
        Center(
          child: SizedBox(
            width: size,
            height: size,
            child: CircularProgressIndicator(
              strokeWidth: 3,
              value: value,
            ),
          ),
        ),
        Center(child: Text(text)),
      ],
    );
  }
Henrieta answered 18/11, 2023 at 23:20 Comment(0)
M
1

A custom circular progress indicator with text, using custom painting and styled text

enter image description here

import 'dart:math';
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: const Scaffold(
        body: Center(
          child: CircularProgressWithText(8),
        ),
      ),
    );
  }
}

class CircularProgressWithText extends StatelessWidget {
  final double percentage;

  const CircularProgressWithText(this.percentage, {super.key});

  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      painter: _CircularProgressPainter(percentage),
      child: Container(
        width: 40,
        height: 40,
        alignment: Alignment.center,
        child: OutlinedText('${percentage.toInt()}%'),
      ),
    );
  }
}

class _CircularProgressPainter extends CustomPainter {
  final double percentage;

  _CircularProgressPainter(this.percentage);

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..strokeWidth = 10
      ..color = Colors.blue
      ..style = PaintingStyle.stroke;

    final center = Offset(size.width / 2, size.height / 2);
    final radius = min(size.width / 2, size.height / 2);

    canvas.drawCircle(center, radius, paint);

    final progressPaint = Paint()
      ..strokeWidth = 10
      ..color = Colors.green
      ..style = PaintingStyle.stroke
      ..strokeCap = StrokeCap.round;

    double arcAngle = 2 * pi * (percentage / 100);

    canvas.drawArc(Rect.fromCircle(center: center, radius: radius), -pi / 2,
        arcAngle, false, progressPaint);
  }

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

class OutlinedText extends StatelessWidget {
  final String text;

  const OutlinedText(this.text, {super.key});

  @override
  Widget build(BuildContext context) {
    final primaryColor = Colors.black.withOpacity(0.5);

    final textStyle = TextStyle(
      shadows: [
        Shadow(
          color: primaryColor,
          blurRadius: 5,
          offset: const Offset(0, 0),
        )
      ],
      color: Colors.white,
      fontSize: 12,
      fontWeight: FontWeight.bold,
    );
    return Stack(
      alignment: Alignment.center,
      children: [
        Text(
          text,
          style: textStyle.copyWith(
            foreground: Paint()
              ..style = PaintingStyle.stroke
              ..color = primaryColor
              ..strokeWidth = 2,
            color: null,
          ),
        ),
        Text(text, style: textStyle),
      ],
    );
  }
}
Mistranslate answered 19/12, 2023 at 2:38 Comment(0)
P
0

Use Positioned They are meant to be used with Stacks.

As per documentation:

A Positioned widget must be a descendant of a Stack, and the path from the Positioned widget to its enclosing Stack must contain only StatelessWidgets or StatefulWidgets (not other kinds of widgets, like RenderObjectWidgets).

Also, don't forget to wrap your Stack inside a Container or Center so as to put constraints to the box.

Piliferous answered 10/12, 2018 at 17:33 Comment(0)
T
0
Column(
  children: <Widget>[
    SizedBox(
      height: 40,
      child: Stack(
        children: <Widget>[
          Container(
            width: 40,
            height: 40,
            child:
                new CircularProgressIndicator(
              value: 10,
              color: Colors.red,
            ),
          ),
          Positioned(
            bottom: 0,
            left: 0,
            right: 0,
            top: 15,
            child: Text(
              bytesDownload!,
              textAlign:
                  TextAlign.center,
              style: TextStyle(
                fontSize: 10,
              ),
            ),
          ),
        ],
      ),
    ),
  ],
);
Trap answered 17/9, 2021 at 17:24 Comment(1)
Answer needs supporting information Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Betthezel
C
-1

Just Wrap it inside a SizedBox()

https://i.sstatic.net/fJfaL.png

Crawly answered 25/11, 2022 at 18:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.