I've painted a shape for the background of my content of Text
.
I want the background autoscale the Text, even the softWrap
being true.
So, I need to get the width and height of my Text Widget before Widget build(BuildContext context)
.
Actually, I am simulating the chat bubble effect like iOS message using flutter. Here is the iOS version tutorial. Creating a Chat Bubble .
The core code below:
let label = UILabel()
label.numberOfLines = 0
label.font = UIFont.systemFont(ofSize: 18)
label.textColor = .white
label.text = text
let constraintRect = CGSize(width: 0.66 * view.frame.width,
height: .greatestFiniteMagnitude)
let boundingBox = text.boundingRect(with: constraintRect,
options: .usesLineFragmentOrigin,
attributes: [.font: label.font],
context: nil)
label.frame.size = CGSize(width: ceil(boundingBox.width),
height: ceil(boundingBox.height))
let bubbleSize = CGSize(width: label.frame.width + 28,
height: label.frame.height + 20)
let width = bubbleSize.width
let height = bubbleSize.height
=========================================
SOLUTION
Here is my solution.
bubble.dart:
// Define a CustomPainter to paint the bubble background.
class BubblePainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final Paint paint = Paint()
..color = Color(0xff188aff)
..style = PaintingStyle.fill;
final Path bubble = Path()
..moveTo(size.width - 22.0, size.height)
..lineTo(17.0, size.height)
..cubicTo(
7.61, size.height, 0.0, size.height - 7.61, 0.0, size.height - 17.0)
..lineTo(0.0, 17.0)
..cubicTo(0.0, 7.61, 7.61, 0.0, 17.0, 0.0)
..lineTo(size.width - 21, 0.0)
..cubicTo(size.width - 11.61, 0.0, size.width - 4.0, 7.61,
size.width - 4.0, 17.0)
..lineTo(size.width - 4.0, size.height - 11.0)
..cubicTo(size.width - 4.0, size.height - 1.0, size.width, size.height,
size.width, size.height)
..lineTo(size.width + 0.05, size.height - 0.01)
..cubicTo(size.width - 4.07, size.height + 0.43, size.width - 8.16,
size.height - 1.06, size.width - 11.04, size.height - 4.04)
..cubicTo(size.width - 16.0, size.height, size.width - 19.0, size.height,
size.width - 22.0, size.height)
..close();
canvas.drawPath(bubble, paint);
}
@override
bool shouldRepaint(BubblePainter oldPainter) => true;
}
// This is my custom RenderObject.
class BubbleMessage extends SingleChildRenderObjectWidget {
BubbleMessage({
Key key,
this.painter,
Widget child,
}) : super(key: key, child: child);
final CustomPainter painter;
@override
RenderCustomPaint createRenderObject(BuildContext context) {
return RenderCustomPaint(
painter: painter,
);
}
@override
void updateRenderObject(
BuildContext context, RenderCustomPaint renderObject) {
renderObject..painter = painter;
}
}
Use the BubbleMessage
Widget like this:
import 'bubble.dart'
...code ...
BubbleMessage(
painter: BubblePainter(),
child: Container(
constraints: BoxConstraints(
maxWidth: 250.0,
minWidth: 50.0,
),
padding: EdgeInsets.symmetric(horizontal: 15.0, vertical: 6.0),
child: Text(
'your text variable',
softWrap: true,
style: TextStyle(
fontSize: 16.0,
),
),
),
),
...code ...
The bubble effect:
First, you need to assign a GlobalKey to the widget. If you've assigned the GlobalKey to the widget, you can get the currentContext property of the key and call the findRenderObject() method. The result can be casted to RenderBox . You can get the size from the RenderBox 's size property.
To find length of a given string in Dart, you can use length property of String class. String. length returns an integer specifying the number of characters in the string or otherwise called length.
To change the TextField height by changing the Font Size: Step 1: Inside the TextField, Add the style parameter and assign the TextStyle(). Step 2: Inside the TextStyle(), Add the fontSize parameter and set the appropriate value. Step 3: Run the app.
SizedBox is a built-in widget in flutter SDK. It is a simple box with a specified size. It can be used to set size constraints to the child widget, put an empty SizedBox between the two widgets to get some space in between, or something else.
In Flutter, you can easily get the size of a specific widget after it’s rendered. What you need to do is to give it a key, then using that key to access currentContext.size property, like this:
You can change the font size of text in a Text Widget using style property. Create a TextStyle object with fontSize and specify this object as style for Text Widget. A quick code snippet is shown below. Change the value for fontSize to change the font size of text in Text Widget.
This article shows you how to set the width, height, and inner padding of a TextField widget in Flutter. You can set the width of a TextField exactly as you want by wrapping it inside a Container, a SizedBox, or a ContrainedBox widget.
The different screen has different sizes, so the widget tree, you can auto-resize them according to the screen in Flutter. See the example below: First, you need to add auto_size_text widget in your project by adding the following lines in pubspec.yaml file. Now to import the package in your script:
My apologies. This is not a direct answer on the topic's question! But If someone needs to get the size of a Text widget — this method can help. It helped me in creation of custom menu widget.
class TextSized extends StatelessWidget {
const TextSized({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
final String text = "Text in one line";
final TextStyle textStyle = TextStyle(
fontSize: 30,
color: Colors.white,
);
final Size txtSize = _textSize(text, textStyle);
// This kind of use - meaningless. It's just an example.
return Container(
color: Colors.blueGrey,
width: txtSize.width,
height: txtSize.height,
child: Text(
text,
style: textStyle,
softWrap: false,
overflow: TextOverflow.clip,
maxLines: 1,
),
);
}
// Here it is!
Size _textSize(String text, TextStyle style) {
final TextPainter textPainter = TextPainter(
text: TextSpan(text: text, style: style), maxLines: 1, textDirection: TextDirection.ltr)
..layout(minWidth: 0, maxWidth: double.infinity);
return textPainter.size;
}
}
Problem with other answers is that if you use Text
widget to display your text and constraint it with measurements result without considering default font family and scale factor, then you will get wrong results because Text
widget is using device's textScaleFactor
by default and passing it to RichText
widget inside of it. This is the correct code to measure text size:
final Size size = (TextPainter(
text: TextSpan(text: text, style: textStyle),
maxLines: 1,
textScaleFactor: MediaQuery.of(context).textScaleFactor,
textDirection: TextDirection.ltr)
..layout())
.size;
I found another method without using the context
:
final constraints = BoxConstraints(
maxWidth: 800.0, // maxwidth calculated
minHeight: 0.0,
minWidth: 0.0,
);
RenderParagraph renderParagraph = RenderParagraph(
TextSpan(
text: text,
style: TextStyle(
fontSize: fontSize,
),
),
textDirection: ui.TextDirection.ltr,
maxLines: 1,
);
renderParagraph.layout(constraints);
double textlen = renderParagraph.getMinIntrinsicWidth(fontSize).ceilToDouble();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With