In Flutter, non-english language in Text Widget has strange margin value - flutter

I'm a developer who just started flutter.
While using the flutter to configure a screen, I visited to ask about something strange.
I set the crossAxisAlignment option to center in the Row widget and set one of the children to Text.
The code is here.
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
SizedBox(width: 22.0),
Text(
'Test',
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.w500,
fontStyle: FontStyle.normal),
),
],
),
Then, I created the text in Korean.
The result is the same as the picture below, but as you can see, the upper and lower margins of the letters are slightly different (it is slightly skewed down).
If this is English, the top and bottom margins are the same as follows.
This issue is the same for all Widgets written in Korean, but does anyone know the solution to this?

It seems there might be a similar issue logged here.
The proposed solution (although there is no input from OP to indicate it worked), is to pass textAlign: TextAlign.center to your Text Widget. This might help as crossAxisAlignment is a property applied via Row and Column to their children, whereas TextAlign is applied to the Text widget directly. Perhaps in conjunction with crossAxisAlignment it might produce the desired result.
That or you might want to experiment with padding on the Text widget. You can do this by wrapping your Text widget in a Padding widget or in a Container widget. See below.
Padding
Padding(
padding: EdgeInsets.fromLTRB(20, 20, 20, 20),
child: Text('Padding Via Padding Widget',
style: TextStyle(fontSize: 22))),
)
Container
Container(
padding: EdgeInsets.fromLTRB(20, 20, 20, 20),
child: Text('Padding Via Container Widget',
style: TextStyle(fontSize: 22)),
)

Related

How to make a large distance between widgets

Tell me how to correctly make a large indent between RedeemButton() and button ? I need to make such an indent as shown in the screenshot.
body
Column(childre: [
const RedeemButton(
textStyle: constants.Styles.smallBookTextStyleWhite,
buttonStyle: constants.Styles.smallMediumTextStyleWhite),
const Padding(
padding: EdgeInsets.only(bottom: 50),
child: Text(
'Hello',
style: TextStyle(
color: Colors.white,
),
),
),
As you are using a Column Widget, to separate your 2 children you can use the mainAxisAlignment set to spaceBetween, like this:
Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [...
If you want a spacific distance number, you can set a SizedBox Widget between them, and set a height that fits your need in a height property
You can use Spacer widget if you want.

What's the best way to add space between mapped items in a column

So I have created a simple list using the map function and I want to add some space between each of the items, currently I have used a Column as a wrapper and then added Sized box to create space between each item.
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: hobbies
.map((hobby) => (Column(children: [
Text(hobby,
style: TextStyle(
color: Colors.amberAccent[200],
fontSize: 16,
fontWeight: FontWeight.w600,
)),
SizedBox(
height: 5,
)
])))
.toList(),
),
But it does not seem right to add columns inside a column and additionally the column are getting generated for nothing more than the purpose of wrapping the two items, I want to know if there is a better way to achieve the same results, Thanks.
There are many ways like using spaceBetween property, adding SizeBox, and providing Padding and margin. One of the simplest is using padding in your case. like
(hobby)=> Padding(
padding: const EdgeInsets.only(top:5.0) //or use bottom only,
child: Text(hobby,
style: TextStyle(
color: Colors.amberAccent[200],
fontSize: 16,
fontWeight: FontWeight.w600,
)),
)
You can use mainAxisAlignment of MainAxisAlignment.spaceBetween OR MainAxisAlignment.spaceAround OR MainAxisAlignment.spaceEvenly on the Column for spacing.
On another note Column inside another Column is perfectly fine.
You can also use Wrap widget which can get a direction and then act like a Column or Row. The Wrap widget has spacing property you can read more about it here: https://api.flutter.dev/flutter/widgets/Wrap-class.html
You can pick either of the 3 options. Let me know if you need anything else :)
Instead of mapping, you could use fold (Docs: https://api.dart.dev/stable/2.12.2/dart-core/Iterable/fold.html)
Example:
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: hobbies
.fold([], (arr, hobby) => [
...arr,
Text(hobby,
style: TextStyle(
color: Colors.amberAccent[200],
fontSize: 16,
fontWeight: FontWeight.w600,
)),
SizedBox(
height: 5,
)
]),
),
This way you'll avoid nested columns, but still be able to use the SizedBox if that's exactly what you need.
Please consider you could wrap the text in a Padding too, instead of separating with SizedBox, and this would allow you to use map again.

How can I align the Flutter Text Widget Vetically?

I am trying to align these text widgets vertically so that they are perfectly centered between the two lines. However, flutter sees the size of the text widget to be as big as the red rectangle behind the text (Background color of text only for illustration purposes) because of the decender line. However, this results in the text looking a bit offcentered. Is there a way to align the text using the baseline and not the decender?
Play with the text height (line-height)
Text('Hey There',
style: TextStyle(height: 5, fontSize: 10),
)
You can try Align widget just wrap your text with Align and provide your alignment
Wrap it in a center widget
Center(
child: Text(
"PAYMENT",
style: TextStyle(
backgroundColor: Colors.blue,
fontSize: 20,
),
textAlign: TextAlign.center,
),
)
Dartpad:
https://dartpad.dev/flutter?null_safety=true&id=3b0bf085892c1867012f5dd00713ccf7
I think what your looking for is to use the "CrossAxisAlignment" attribute in the Column widget.
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('Delivery'),
Text('Payment'),
Text('Total'),
],
)

Set spacing between two lines of text

I am trying to set spacing between two lines of text, but am not able to. Right now, the two lines are rendering after each other, but i want a bit of spacing between that i can adjust. I have tried using the Spacer widget but this makes the spacing too large. Is there a better way to do this?
Expanded(
child: Column(
children: <Widget>[
Text("We're finding your pizza.",
style: theme.textTheme.body1.copyWith(fontSize: 18)),
Text(
"We'll send you a notification.",
textAlign: TextAlign.center,
style: theme.textTheme.body1.copyWith(fontSize: 18)),
],
),
),
You can also set a specific padding between text lines by setting the height property in the TextStyle. With this you set the height for each line.
Text(
"Let's make\nsome pancakes",
style: TextStyle(
height: 1.2, //SETTING THIS CAN SOLVE YOUR PROBLEM
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.w300,
),
textAlign: TextAlign.center,
),
In fact, we can confirm from the docs that:
For most fonts, setting height to 1.0 is not the same as omitting or setting height to null because the fontSize sets the height of the EM-square, which is different than the font provided metrics for line height.
For more info: https://api.flutter.dev/flutter/painting/TextStyle/height.html
I posted this same answer at Flutter how do I remove unwanted padding from Text widget? to get the opposite result but it works the same way.
Spacer will take up all the available spaces left, and you may not need this. So you can simply use SizedBox widget.
Text("One"),
SizedBox(height: 20), // use this
Text("Two"),
you can simply use the SizedBox widget or Container widget with padding.
SizedBox(height: 15.0)
or
Container(
padding: const EdgeInsets.all(15.0))

Flutter how do I remove unwanted padding from Text widget?

I have a Text widget and not sure why it seems to just have padding at the top and bottom even though I didn't set any in the code. This is from the default Flutter app, I just modified the font size.
body: Center(
child: Column(
children: <Widget>[
Text(
'0:00.00',
style: TextStyle(fontSize: 76),
),
],
),
),
This is a screenshot of the highlighted Text widget in Android Studio. There's really nothing else adding any padding so I don't know why it's there.
Sometimes you get this in CSS where there is padding even though none was set but you can remove it simply with padding: 0 but I don't see how to do it here since I can't find a padding option for the Text widget.
EDIT: The amount of padding changes with the size of the font. It seems to always contain a certain amount of padding, like a html H1 tag.
The proper way you can get rid of the unwanted padding is by setting the height property in the TextStyle. With this you set the height for each line.
Text(
"Let's make\nsome pancakes",
style: TextStyle(
height: 1.2, //SETTING THIS CAN SOLVE YOUR PROBLEM
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.w300,
),
textAlign: TextAlign.center,
),
In fact, we can confirm from the docs that:
For most fonts, setting height to 1.0 is not the same as omitting or setting height to null because the fontSize sets the height of the EM-square, which is different than the font provided metrics for line height.
For more info: https://api.flutter.dev/flutter/painting/TextStyle/height.html
So give it a try. It worked for me.
There are reasons why the Text widget has this "padding". Take in consideration the next example:
Text(
'123 gyÓ',
style: TextStyle(
fontSize: 40.0,
),
),
As we can see, using another characters like the letters g and y and an uppercase O with an accent marker, shows us that there's no padding on the Text widget really.
Fonts have ascenders and descenders on some characters, and there's also en ascent line for special characters like the accent marker. That's why numbers are centered in the middle. That's not padding on Flutter side, but typography design(?). Maybe you could find a way to sort your issue, by looking for a font without ascenders and descenders.
More info about fonts on Wikipedia
Conclusion: if you want to select the Text widget with the Flutter inspector, and see no space around some characters, that is not possible.
I think I found a good solution/workaround for removing both top and bottom padding.
The trick is to put your Text in a Container and then change the height of your TextStyle inside the Text, as well as the height of your Container. It's a bit of going back and forth for the perfect measurements but it's worth it imo.
Here's an example from my own code.
Container(
height: 24,
child: Text(
'Auto',
style: TextStyle(
height: 0.77,
fontSize: 32,
fontWeight: FontWeight.bold,
color: Colors.white,
),
textAlign: TextAlign.center,
),
There are 2 potential reasons:
The fontFamily - try commenting it out and see if you still have the same problem. If this is the reason and you absolutely must/want to use this specific font, I'm not sure what the fix is, apart from some horrible logic to stack widgets accordingly so that it looks like there's no padding.
Layout constraints from the parent Widgets - you only included the code of the Text widget, but if for example it's wrapped in an Expanded widget within a Column, that would also explain the extra height (possibly wrong assumption here because the text wouldn't center itself vertically by default anyway, but then there might be a DefaultTextStyle widget up in the hierarchy somewhere so still possible....)
Edit: It seems like there is some default padding around the text.
I found that you can reduce the top padding by setting a TextStyle with a height lower than 1. The value required seems to depend on the font size and the text itself, as different characters have different heights.
You can also reduce the bottom padding by clipping the Text using a fixed size Container. This will also vary based on the font size and the text itself. Below is an example of using both of these to reduce the top and bottom padding to 0 for the text '0:00.00' of font size 72:
ClipRect(
child: Container(
height: 55,
child: Text("0:00.00",
style: TextStyle(
fontSize: 72,
height: 0.80,
),
),
),
),
I know this is a very poor solution, but I don't know of any better one. I tried using a custom StrutStyle on the Text widget, but that didn't help either.
Try playing with line height of the text by setting height in style property. Height of the text is determined based on font size. It will multiply the font size and give you the space that will look like it has some padding. The line height of the text is also linked to the font itself, since every font has it own line height.
child: Text(
'Some text goes here',
style: TextStyle(
fontSize: 25.0,
height: 1,
),
)
I found the solution myself in the end. It can be positioned using Stack and Row widgets. I found Row works better than using Positioned as the text can be centred using the Row widgets.
body: Stack(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'0:00.00',
style: TextStyle(fontSize: 76),
),
],
),
Padding(
padding: EdgeInsets.only(top: 56.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Coke',
style: TextStyle(fontSize: 76),
),
],
),
),
],
)
It kind of works like the negative padding in CSS but actually it's the padding that moves the bottom text down rather than up since otherwise they occupy the same space.
After googling a while, I've written this.
What does it do? It's shifting down the position of the text
(not shrinking)
import 'package:vector_math/vector_math_64.dart';
import 'package:flutter/material.dart';
class BaselineText extends StatefulWidget {
final Widget child;
BaselineText({this.child});
#override
_BaselineTextState createState() => _BaselineTextState();
}
class _BaselineTextState extends State<BaselineText> {
GlobalKey _key = GlobalKey();
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {}));
}
#override
Widget build(BuildContext context) {
final RenderBox renderBox = _key.currentContext?.findRenderObject();
final height = renderBox?.size?.height ?? 0;
return Baseline(
baseline: 0,
baselineType: TextBaseline.ideographic,
key: _key,
child: Transform(
transform: Matrix4.translation(
Vector3(0, height, 0),
),
child: widget.child,
),
);
}
}
How to use:
BaselineText(
child: Text("something"),
)
DONE!!!