The fonts of the text in my text widget are dynamic. The width and height of the font change according to different font types. How to get the width or height value of the text widget that varies according to the font.
you can use a GlobalKey into the Text Widget and then check its size somewhere else
GlobalKey myKey = GlobalKey();
...
Text('MyText, key: myKey)
Then use the currentContext of the GlobalKey to check its size (in a callback after it has been built)
print(myKey?.currentContext?.size);
But before doing that you need to build the Text Widget
The current context is null if there is no widget in the tree that
matches this global key
If you want to know the size it will use before creating the TextWidget you can try creating a TextSpan somewhere (in the initState for example)
TextSpan longestParagraphTest = TextSpan(
text: "This is all my Text",
style: myTextStyle, //define the style it willl use, fontSize, etc.
);
TextPainter _textPainter = TextPainter(text: longestParagraphTest, textDirection: TextDirection.ltr, maxLines: 1)..layout(minWidth: 0.0, maxWidth: double.infinity);
width = _textPainter.width; //This is the width it requires
height = _textPainter.height; //This is the height it requires
Related
I'm trying to create a expand-able container that have a specific height of 150 when it shrink and only show maximal 2 line of text.
But when the user click on the container it will expand to height of depending on the text if the text from the database is 10 line the height have to be 10 line but when the max text is 20 the height need to adjust to 20 line.
Can I achieve it using animatedContainer or animatedSize ?
Yes you can use an animated container..
bool widgetExpanded = false;
InkWell
(
onTap :(){
setState((){
widgetExpanded = !widgetExpanded;
});
}
child : AnimatedContainer(
height : widgetExpanded ? 300:150, //<-- optional. Only if you wish to add height
duration: Duration(milliseconds: 500),
child: Text("Some big text here", style: TextStyle(
maxLines: widgetExpanded? null: 2,
overflow: TextOverflow.ellipsis,
))
)
)
Also please take a look at expansion tile
https://api.flutter.dev/flutter/material/ExpansionTile-class.html
Use ExpansionTile to create that animation, it is expanded to your text or any widget as you like.
In the image you see that some texts take more space than the width provided by their parent widget. I want to use marquee so that when the text is longer than the width, it scrolls. But, it should not always be scrollable, only when it is longer, not even when the text is fitted inside the parent widget. How can I use marquee only when the text is long?
bool _willTextOverflow({required String text, required TextStyle style}) {
final TextPainter textPainter = TextPainter(
text: TextSpan(text: text, style: style),
maxLines: 1,
textDirection: TextDirection.ltr,
)..layout(minWidth: 0, maxWidth: maxWidth);
return textPainter.didExceedMaxLines;
}
Read more about this here.
Get the entire code here.
I use MarkdownBody from flutter_markdown inside a LimitedBox. When pressing a "Show more" button the maxHeight is set to double.infinity and the full text is shown:
LimitedBox(
maxHeight:
showMoreCommentsIds
.contains(
commentId)
? double.infinity
: 100,
child: Wrap(
direction:
Axis.horizontal,
children: <Widget>[
MarkdownBody(
data: showList[index]
.comment
.comment,
)
],
),
),
But how can I find out the height of the text and only display the "Show more" button, if it is necessary?
You can find the length of the text using text.length and based on that information determine if the "Show more" button is needed. For example:
if(text.length > 60) {
_showButton();
}
You may need to do a little testing with the length of text in order to find out which length you want as the threshold. I just chose 60 as an arbitrary number.
I struggled a little bit with a similar problem because I had to know the size of a widget to apply some logic.
I learned that you can prerender the widget in an Offstage widget, determine it's size with the widget key once it is mounted.
You should wait for the rebuild, so you can force it and then you get the size with a function like this:
Future.delayed(Duration(milliseconds:100)).then(
final widgetSize = getWidgetSize(widgetKey);
// You can make logic here to remove the Offstage, variables, and free its space.
// Todo: apply the size in your code after this
)
...
Size getWidgetSize(GlobalKey key) {
final RenderBox renderBox = key.currentContext.findRenderObject();
return renderBox.size;
}
In my case, I needed it after tapping somewhere, so I used it inside a function, but maybe you will apply it directly on the initState(), inside a post frame callback.
initState(){
super.initState();
ServicesBinding.instance.addPostFrameCallback((_) async {
// here
});
}
I want to change my Text Widget font family on button click.
Which means I created a Container and in this Container I added multiple text style widget with GestureDetector widget. So whenever I click on Particular font family, I want to change my Text widget Font-Family.
Any suggestion for doing this type of functionality.
Hope this works or modify accordingly:
code inside your Text Widget:
Text("Your Text",
style: tapped
?TextStyle(fontFamily: 'Your-Font-Family')
:TextStyle(fontFamily: 'Your-Second-Font-Family'),
),
code inside Gesture Detector:
GestureDetector(
child: your child widget,
onTap: () {
setState(() {
tapped = !tapped;
});
}),
and remember to define bool tapped; in your widget class.
Still, if you face any difficulty, add the code to comment so I can help you out.
Use a variable to store font name
reference it in your text Widget
then call setState to update the value of variable and UI
String fontName;
//your TextWidget
Text("some text for testing",
style: TextStyle( fontFamily: fontName )
)
//function to update the value
_updateFont(String name){
setState((){
fontName = name;
});
}
make sure you are importing the fonts to be used
add them in pubspec.yaml file under fonts
- family: font1
fonts:
- asset: assets/fonts/font1.ttf
I am trying to add an editable textbox to the canvas in Flutter, that will bring up the keyboard once selected.
I am using a custom painter to print text to a canvas (shown in the code below). Is it possible to make this text editable, or add a text input element over the canvas at a particular offset?
import 'package:flutter/material.dart' as Material;
class CanvasPainter extends Material.ChangeNotifier implements Material.CustomPainter {
..
void paint(Canvas canvas, Size size) {
Material.TextSpan textSpan = new Material.TextSpan(style: new material.TextStyle(color: new Maaterial.Color.fromRGBO(r, g, b, 1.0), fontSize: font.fontSize.toDouble(), fontFamily: 'Roboto'),text: "Hello there");
Material.TextPainter tp = new Material.TextPainter( text: textSpan, textAlign: TextAlign.left, textDirection: TextDirection.ltr, textScaleFactor: ratio);
tp.layout();
tp.paint(canvas, new Offset(50.0,50.0));
}
}
Not the best solution, but I could solve similar issue with OverlayEntry.
Steps:
create an OverlayEntry, put a (hidden) TextField into it with a FocusNode and TextEditController.
after added the overlay entry, request focus on the focusNode, so the keyboard will open.
Add an onChanged to the TextField, and notify the painter somehow (e.g. valueNotifier) on text change.
In the TextPainer use the TextEditController.text value