Search code examples
flutterdarttextsqfliteflutter-custompainter

Centering Text in an Arc - Flutter


enter image description hereI am trying to center the Text within an arc in a flutter app. There are two elements in this.

First the arcs with colors are painted on the canvas and the Text is stacked over it.

The distance of each arc varies and is also dynamic based on the user choice. This is called from a sqflite database. I have provided the static list here for example only.

The code for the same is as below:

import 'dart:math'; 
import 'package:flutter/material.dart';

class OuterRing extends StatelessWidget {
  final double width;
  final double height;
  
  const OuterRing(
      {Key? key,
      required this.width,
      required this.height,
      })
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.transparent,
      body: Stack(
        children: [
          CustomPaint(
            painter:
                Ring(width: width, height: height),
          )
        ],
      ),
    );
  }
}

class Ring extends CustomPainter {
  final double width;
  final double height;
 

  Ring(
      {required this.width, required this.height});
  @override
  void paint(Canvas canvas, Size size) {
    double sizedim = width / 1.5;
    double offsetdim = sizedim / 2;
    double strkwidth = 18;

    List<Color> colors = [
      const Color.fromRGBO(255, 179, 186, 1),
      const Color.fromRGBO(255, 223, 186, 1),
      const Color.fromRGBO(255, 255, 186, 1),
    ];

    List<double> start = [
      -66.96,
      -95.085,
      -122.2725,
      -150.3975,
      -177.585,
      -233.835,
      -261.0225,
      -289.1475,
      -316.335,
      -344.46,
      -11.6475,
      -39.7725
    ];

    List<double> sweep = [
      -28.125,
      -27.1875,
      -28.125,
      -27.1875,
      -56.25,
      -27.1875,
      -28.125,
      -27.1875,
      -28.125,
      -27.1875,
      -28.125,
      -27.1875
    ];

    Paint arc(int color) {
      final paint = Paint()
        ..color = colors[color]
        ..style = PaintingStyle.stroke
        ..strokeWidth = strkwidth;
      return paint;
    }
    double rad = 0.0174533;

    int j = 0;
    for (int i = 0; i < 12; i++) {
      if (j == 3 || j == 6 || j == 12) {
        j = 0;
      }
      canvas.drawArc(
          Offset(strkwidth / 2 + width / 2 - offsetdim,
                  strkwidth / 2 + width / 2 - offsetdim) &
              Size(sizedim - strkwidth, sizedim - strkwidth),
          start[i] * rad,
          sweep[i] * rad,
          false,
          arc(j));
      j++;
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    // TODO: implement shouldRepaint
    return false;
  }
}

Next I have the text stack on top of it. Again the text changes based on the user choice. I am using the 'flutter_arc_text' widget to achieve this.

The code for the same is as below:

import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter_arc_text/flutter_arc_text.dart';

class OuterRingText extends StatelessWidget {
  final double width;
  final double height;
  

  const OuterRingText(
      {Key? key,
      required this.width,
      required this.height})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        backgroundColor: Colors.transparent,
        body: Stack(
          children: [for (var i = 0; i < 12; i++) arctext(i)],
        ));
  }

  Widget arctext(count) {
    List<String> names = [
      'First',
      'Second',
      'Third',
      'Fourth',
      'Fifth',
      'Sixth',
      'Seventh',
      'Eighth',
      'Nineth',
      'Tenth',
      'Eleventh',
      'Twelfth'
    ];
    
    List<double> start = [
      -66.96,
      -95.085,
      -122.2725,
      -150.3975,
      -177.585,
      -233.835,
      -261.0225,
      -289.1475,
      -316.335,
      -344.46,
      -11.6475,
      -39.7725
    ];

    return Center(
      child: ArcText(
          radius: 106,
          //text: maasadata[count].maasa.toString(),
          text: names[count],
          textStyle: const TextStyle(
              fontSize: 10, fontWeight: FontWeight.bold, color: Colors.black),
          startAngle: start[count] - start[0]) * 0.0174533,
          startAngleAlignment: StartAngleAlignment.start,
          placement: Placement.outside,
          direction: Direction.clockwise),
    );
  }
}

My question is how can I center the text within each of the arcs. Thanks in advance.


Solution

  • You can use startAngleAlignment: StartAngleAlignment.center parameter which means that the text will be centered on startAngle.

    But it means that as a startAngle you need to provide the center of your sector, looking at your code, I guess it should be something like:

    startAngleAlignment: StartAngleAlignment.center,
    startAngle: (start[count] - start[0] + sweep[count] / 2) * 0.0174533,