Set horizontal alignment in MaterialBanner in Flutter - flutter

I'm trying to set a layout inside MaterialBanner. I need to set the red-colored widget in the bottom to the left. However, I cannot figure it out how and the square widgets are always right-aligned.
Here is my sample code.
If you know how to implement it, I would like to know the tip. Thank you.
MaterialBanner(
forceActionsBelow: true,
actions: <Widget>[
RaisedButton( // Tried Row, Expanded Widget but neither works
child: Text('Red'),
color: Color(0xff49A9EF),
),
RaisedButton(
child: Text('Blue 1'),
color: Color(0xff49A9EF),
),
RaisedButton(
child: Text('Blue 2'),
color: Color(0xff49A9EF),
),
],
content: Text(
'text text text text text text text text text text text text text text text text text text ',
overflow: TextOverflow.ellipsis,
maxLines: 2,
),
...
)

I've tried this and I can answer why the Red Box doesn't move to the left.
The actions list of Widgets is always set to AlignmentDirectional.centerEnd so there is no way you can place a Widget in the actions list and expect it to be elsewhere.
What if the red box was passed to the leading property of the MaterialBanner Widget. Then we see that the box aligns on the top left with the provided content. Even when the padding is stripped off completely from the leading Widget it sticks to the top left.
Any reason why you wouldn't write a custom Widget to accomplish this ?

Related

Flutter, TextFormField Suffix Widget position like youtube

It seems to have been an issue for a long time, is there still no solution?
If you set suffixIcon: it will automatically center when MaxLines is 3. (so it locates at 2nd line)
However, the downside of this is that the top and bottom padding values are a problem.
Therefore, customizing it is easier to just use suffix: to make it a widget.
but with suffix:
When I do
Container(child:Text("Test button"))....
The button height is completely lengthened (by the length of max lines)
I just want to implement like youtube comment suffix icon
At first, it's in the top right corner, and whenever the line changes, I want the send Icon to go down too. Is there still no way? Flutter?
You can use Row widget with CrossAxisAlignment.end
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Expanded(
child: TextFormField(
maxLines: 4,
minLines: 1,
),
),
Icon(Icons.abc) // padding more decoration if needed
],
),

Flutter - Align only one widget inside of a Row

I have a text that can vary in height, followed by a PopupMenuButton. I want the text to be center-aligned on the vertical axis (so that there isn't a weird white space when there's only 1 ligne of text) but the PopupMenuButton to stay in the top right corner, no matter the height of the text. Thus using crossAxisAlignement doesn't work here since all widgets are affected. Using an Align widget on the text or PopupMenuButton doesn't work and textAlign doesn't either It seems any solution must be implemented on the Row level and not in its children, which makes sense.
For now I'm using a Row to contain these 2 widgets, but I'm not so sure it is what I need if I want the behaviour mentionned before. Is there a solution for the Row, or another widget I can use for this ?
Here is the code as it stands. Thanks.
Row(
children: [
Expanded(
child: RichText(
text: TextSpan(), // bunch of text in there
)
)
),
SizedBox( // To box in the 3 dots icon (material design forces 48px otherwise)
height: 24,
width: 24,
child: PopupMenuButton(
padding: EdgeInsets.all(0),
onSelected: menuSelect,
itemBuilder: (BuildContext context) {
return [
PopupMenuItem(value: 0, child: Text('Read', textAlign: TextAlign.center,),),
PopupMenuItem(value: 1, child: Text('Delete', textAlign: TextAlign.center,),)
];
},
),
)
],
)
Here's a way to do it :
Wrap your SizedBox with an Align(alignment: Alignment.topRight)
Wrap your Row with an IntrinsicHeight so that the cross-axis
doesn't stretch
Alternatively, you might want to look into the Stack widget if you're not familiar with it.

how to add icon into text flutter?

i have a simple code
RaisedButton(
onPressed: () {
model.resetmodem();
},
child: Text(
'Size (also 24 pixels, not coincidentally, since both FlutterLogo and Icon honor the ambient IconTheme). This leaves some room left over, and now the row tells the text exactly how wide to be: the exact width of the remaining space. The text, now happy to comply to a reasonable request, wraps the text ',
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
color: Colors.blue,
textColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25)),
),
I want to add an icon in front of the text but I don't want to overflow the text
Use Row and put this text and icon inside it if it overflows you got to lower font sized or icon size or make your button bigger
You could you RichText along with InkWell like:
InkWell(
onTap: () {
//Your code here
},
child: RichText(
text: TextSpan(
text: 'Size (also 24 pixels, not coincidentally, since both FlutterLogo and Icon honor the ambient IconTheme). This leaves some room left over, and now the row tells the text exactly how wide to be: the exact width of the remaining space. The text, now happy to comply to a reasonable request, wraps the text ',
children: [
WidgetSpan(child: Icon(Icons.done)),
]),
),
)

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!!!

How does flutter make textfield dynamically display multiple lines?

The effect I want to achieve is that the initial text field displays one line, and when the content exceeds one line, the text field displays two lines. The problem is that the baseline of the text field will move down, causing it to be obscured by the widget below. I want the baseline to remain in a row.
code:
return Scaffold(
appBar: AppBar(),
body: Column(
children: <Widget>[
ConstrainedBox(
constraints: BoxConstraints(
maxHeight: 60.0
),
child: TextField(
maxLines: null,
maxLengthEnforced: false,
keyboardType: TextInputType.multiline,
),
),
Container(height: 20.0,width: 200.0,color: Colors.red),
],
)
);
The expected effect should be:
One line of text effect:
Multi-line text effect:
Note that the baseline position has not moved down.
Just set the maxLines property to null. The TextField Widget will automatically wrap the text, changing the number of lines dynamically.
Documentation