I need make custom widget (in Flutter) which contains text on specific position. When I draw text by TextPainter, I set TextAlign to center. Text is still drawn with left align. What am I doing wrong?

TextSpan span = TextSpan(style: TextStyle(color: Colors.white, fontSize: textSize), text: 'T');
TextPainter tp = TextPainter(text: span, textAlign: TextAlign.center, textDirection: TextDirection.ltr);
tp.layout();
tp.paint(canvas, Offset(pos.x, pos.y));


Solution 1: MortalFool

for the X position make sure layout is set to 0 for min an max width

textPainter.layout(minWidth: 0, maxWidth: 0); 

for the Y position you have to substract the height of the text itself

final position = Offset(xPOS, yPOS - (textPainter.height / 2));

here is an example code

void _drawTextAt(String text, Offset position, Canvas canvas) {
    final textStyle = TextStyle(
      color: Colors.black,
      fontSize: 30,
    );
    final textSpan = TextSpan(
      text: 'O',
      style: textStyle,
    );
    final textPainter = TextPainter(
        text: textSpan,
        textDirection: TextDirection.ltr,
        textAlign: TextAlign.center);
    textPainter.layout(minWidth: 0, maxWidth: 0);
    Offset drawPosition =
        Offset(position.dx, position.dy - (textPainter.height / 2));
    textPainter.paint(canvas, drawPosition);
  }

To use this function call e.g.

  _drawTextAt('A', Offset(20, 20), canvas);


Solution 2: Mohamed Adly

I used drawParagraph and it works well

final ui.ParagraphBuilder paragraphBuilder = ui.ParagraphBuilder(
        ui.ParagraphStyle(textDirection: ui.TextDirection.ltr),
      )
      ..addText('Your Text');
final ui.Paragraph paragraph = paragraphBuilder.build()
        ..layout(ui.ParagraphConstraints(width: textSize.width));
canvas.drawParagraph(paragraph, textOffset);

you can change the ParagraphStyle the way you like.


Solution 3: Andrey Gordeev

Align a custom painted text with CustomPainter in Flutter

To simply center the text on the canvas, calculate its offset:

void _paintText(Canvas canvas, Size size) {
  final textSpan = TextSpan(
    text: 'n/a',
  );
  final textPainter = TextPainter(
    text: textSpan,
    textDirection: TextDirection.ltr,
  );
  textPainter.layout();
  textPainter.paint(
    canvas,
    Offset(
      // Do calculations here:
      (size.width - textPainter.width) * 0.5,
      (size.height - textPainter.height) * 0.5,
    ),
  );
}


Solution 4: ipcjs

By using Alignment.inscribe, you can align the text in any way. :)

extension CanvasExt on Canvas {
    void drawTextInRect(
        Rect rect,
        Alignment alignment,
        TextPainter painter,
    ) {
        final offsetRect = alignment.inscribe(painter.size, rect);
        painter.paint(this, offsetRect.topLeft);
    }
}


Solution 5: DreamSaddle

double width = 100, height = 200, r = 63;
canvas.drawCircle(Offset(width, height), r, Paint()..color = Colors.purple);
ParagraphBuilder paragraphBuilder =
ParagraphBuilder(ParagraphStyle(textAlign: TextAlign.center))
..addText('Hello');
ParagraphConstraints paragraphConstraints =
ParagraphConstraints(width: r * 2);
Paragraph paragraph = paragraphBuilder.build()
..layout(paragraphConstraints);
canvas.drawParagraph(
paragraph, Offset(width - r, height - paragraph.height / 2));