I want to draw vertical text directly using canvas, but I didn't find such methods,
I only found related parameter TextDirection, but it only support left--right or right--left.
Here is my code:
void drawMeasurementTag(Canvas canvas, Rect limitRect) {
String text = "this is content";
double textFont = 18;
double textWidth = getTextPainter(text, textFont).width;
Paragraph paragraph = getTextBuilder(
text, textFont, Colors.red);
paragraph.layout(ParagraphConstraints(width: textWidth));
tagPos =Offset(0,0) ;
canvas.drawParagraph(paragraph, tagPos);
}
ui.Paragraph getTextBuilder(String text, double textFont, Color color) {
Paint paint = Paint();
paint.color = getTagBackgroundColor();
var builder = ui.ParagraphBuilder(ui.ParagraphStyle(
textAlign: TextAlign.center,
fontSize: textFont,
textDirection: TextDirection.ltr,
maxLines: 1,
));
builder.pushStyle(
ui.TextStyle(
color: color,
textBaseline: TextBaseline.alphabetic,
background: paint),
);
builder.addText(text);
ui.Paragraph paragraph = builder.build();
return paragraph;
}
this is what I want to achieve:
`
You can rotate your widgets in flutter by math package:
import 'dart:math' as math;
Then use this to rotate by 90 degrees:
Transform.rotate(
angle: -math.pi / 2, // edit this angle
child: Card(
child: Text("Rotated text"),
),
)
Related
I am trying to center a Text widget in a custom shape made using Custom Painter i tried laying a Stack widget but it failed i googled and found about TextPainter and tried to use it I dont know if its the right solution but i could not acheive what i wanted
I want to achieve the button with green arrow i currently have the button with yellow arrow
Any Idea?
class CustomShape1 extends CustomPainter{
#override
void paint(Canvas canvas, Size size) {
TextPainter textPainter = TextPainter(
text: TextSpan(
text: 'Foo\nBar',
style: TextStyle(
color: Colors.white,
fontSize: 30,
),
),
textDirection: TextDirection.ltr,
textAlign: TextAlign.center
);
Paint fillPaint = Paint();
fillPaint.color = const Color(0xFF830B2C);
fillPaint.style = PaintingStyle.fill;
Path path = Path();
path.moveTo(size.width*0.5000125,size.height*0.2996000);
path.cubicTo(size.width*0.6875031,size.height*0.2990750,
size.width*0.6871875,size.height*0.2979000,size.width*0.7500000,size.height*0.2989000);
path.quadraticBezierTo(size.width*0.7645125,size.height*0.5243200,
size.width*0.9373000,size.height*0.6009200);
path.lineTo(size.width*0.9373000,size.height*0.6395600);
path.lineTo(size.width*0.5000500,size.height*0.6401600);
path.quadraticBezierTo(size.width*0.5000406,size.height*0.5550200,
size.width*0.5000125,size.height*0.2996000);
path.close();
canvas.drawPath(path, fillPaint);
textPainter.layout(
minWidth: 0,
maxWidth: size.width,
);
final offset = Offset(50 - (textPainter.width / 2), 100 - (textPainter.height / 2));
textPainter.paint(canvas,offset);
}
#override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return false;
}
}
After inspecting your canvas, you can see that it is not drawn correctly, so you do not see the text on the shape.
final offset = Offset(size.width / 2 + 50, size.height / 2); //text offset
either remake the shape, or try to adjust to this offset, this will give you the visibility of the text on the shape for a start
Hi I want to draw a filled rect with a text inside using canvas.
This is my code:
Rect rect = Rect.fromLTWH(x,y,size,size,);
Paint paint = Paint()..color = Colors.blue;
canvas.drawRRect(RRect.fromRectAndRadius(rect, Radius.circular(100.0)),paint,);
I don't know how to put a text inside a rect. Please help
Use TextPainter class.
You can play around with the offset yourself
TextPainter painter;
painter = TextPainter(
textAlign: TextAlign.center,
textDirection: TextDirection.ltr,
);
painter.text = TextSpan(
text: 'Sample Text',
style: TextStyle(
color: Colors.black,
fontSize: 40.0,
),
);
Offset position = Offset(
x+2.0,
y+2.0,
);
painter.layout();
painter.paint(canvas, position);
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));
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,
),
);
}
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);
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));
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);
}
}
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.
For text drawing on canvas, a fairly simple construction can be used:
void drawName(Canvas context, String name, double x, double y)
{
TextSpan span = new TextSpan(
style: new TextStyle(color: Colors.blue[800], fontSize: 24.0,
fontFamily: 'Roboto'), text: name);
TextPainter tp = new TextPainter(
text: span, textAlign: TextAlign.left, textDirection: `
` TextDirection.ltr);
tp.layout();
tp.paint(context, new Offset(x, y));
}
Is it possible to draw text at an angle, for example 45 degrees, or 90 degrees (vertically from the bottom up)?
To rotate text on a canvas, you can use canvas transforms rather than rotating the entire canvas.
That looks something like this:
#override
void paint(Canvas canvas, Size size) {
// save is optional, only needed you want to draw other things non-rotated & translated
canvas.save();
canvas.translate(100.0, 100.0);
canvas.rotate(3.14159/4.0);
TextSpan span = new TextSpan(
style: new TextStyle(color: Colors.blue[800], fontSize: 24.0,
fontFamily: 'Roboto'), text: "text");
TextPainter tp = new TextPainter(
text: span, textDirection: TextDirection.ltr);
tp.layout();
tp.paint(canvas, new Offset(0.0, 0.0));
// optional, if you saved earlier
canvas.restore();
}
Note that I'm translating then rotating, because if you translate after or even use the offset you'll probably get a different result than what you want. Also, once you start using transforms (translate & rotate) you probably want to save the transform state and then restore after you draw whatever you want transformed, at least if you're drawing anything other than the rotated text.
It sounds like you are looking for a Transformation. There is a general Transform Widget, but there is also a more specific RotatedBox Widget that sounds like it will be a perfect fit for you.
new RotatedBox(
quarterTurns: 3,
child: const Text('Hello World!'),
)
If you need more control over the rotation (to use something other than 90 degree increments) you should be able to achieve this the Transform Widget and a Matrix4.rotationZ
new Container(
color: Colors.blue,
child: new Transform(
transform: new Matrix4.rotationZ(-0.785398),
child: new Container(
padding: const EdgeInsets.all(8.0),
color: const Color(0xFFE8581C),
child: const Text('Apartment for rent!'),
),
),
)
A function that draws text at a specified angle:
void drawText(Canvas context, String name, double x, double y, double angleRotationInRadians)
{
context.save();
context.translate(x, y);
context.rotate(angleRotationInRadians);
TextSpan span = new TextSpan(
style: new TextStyle(color: Colors.blue[800], fontSize: 24.0,
fontFamily: 'Roboto'), text: name);
TextPainter tp = new TextPainter(
text: span, textAlign: TextAlign.left,
textDirection: TextDirection.ltr);
tp.layout();
tp.paint(context, new Offset(0.0,0.0));
context.restore();
}
PS."rmtmckenzie", thank a lot for your help.
When using Text widget with big strings, it happens that the displayed text is splitted on 2 or more lines.
My question is simple : How to know the exact character where a string is divided ?
I've digged inside Text code. Up to dart:ui's Paragraph. But I haven't found anything usable.
Actually the text in flutter is painted on canvas using a TextPainter which computes the layout size during runtime with the box constrains of its parent class. If you already know the available space, you can compute the layout width of the text and compare it with the available width to know where the text would break.
You can computer the width of the text with TextPainter like:
final TextPainter paint = new TextPainter(
text: new TextSpan(
text: "Hello World",
),
textDirection: TextDirection.ltr
);
paint.layout();
debugPrint(paint.width.toString());
You can also do it with CustomPainter like this:
import 'package:flutter/material.dart';
void main() {
String text = "Hello World";
void textShownOnUI(int size){
debugPrint(text.substring(0,size));
}
runApp(new MaterialApp(
title: "Example",
home: new Container(
width: 100.0,
padding: const EdgeInsets.all(175.0),
child: new CustomPaint(
painter: new MyTextWidget(
text: text,
style: new TextStyle(),
notifySize: textShownOnUI
),
child: new Container(),
),
),
));
}
class MyTextWidget extends CustomPainter {
Function notifySize;
String text;
TextStyle style;
TextDirection direction;
MyTextWidget({this.text,this.notifySize,this.style,this.direction});
#override
void paint(Canvas canvas, Size size){
debugPrint(size.width.toString());
final TextPainter _painterWithConstrains = new TextPainter(
text: new TextSpan(
text: text,
style: style
),
textDirection: direction??TextDirection.ltr
);
String _willBeShownOnUI = text;
int _size = text.length;
TextPainter _temp = new TextPainter(
text: new TextSpan(
text: _willBeShownOnUI,
style: style
),
textDirection: direction??TextDirection.ltr
);
_painterWithConstrains.layout(maxWidth: size.width);
_temp.layout();
while(_temp.width > _painterWithConstrains.width && _size != 0){
debugPrint(_temp.width.toString()+" "+ _size.toString());
_willBeShownOnUI = _willBeShownOnUI.substring(0, --_size);
_temp = new TextPainter(
text: new TextSpan(
text: _willBeShownOnUI,
style: style
),
textDirection: direction??TextDirection.ltr
);
_temp.layout();
}
_size = _willBeShownOnUI.split(" ")[0].length; // Get complete words that will be shown
Function.apply(notifySize,<int>[_size]);
_painterWithConstrains.paint(canvas, Offset.zero);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}
Hope that helped!