Flutter, TextFormField Suffix Widget position like youtube - flutter

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
],
),

Related

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.

Set horizontal alignment in MaterialBanner in 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 ?

Flutter baseline text alignment with Wrap class

Using the Row class, I can make the text baseline aligned with this property:
crossAxisAlignment: CrossAxisAlignment.baseline,
But this property seems not to be available on the Wrap class.
The benefit of using Wrap instead of Row is that it allows having multiline text. While the Row class force the content to stay into one line.
How can I keep the benefit of Wrap, while making the text baseline aligned?
I also had this problem. There is an open issue in the Flutter Repo addressing this. While the built-in solution is not implemented yet, I did come up with a slightly-hacky workaround.
Basically, depending on your font and your needs...
Set your Wrap() to have crossAxisAlignment: WrapCrossAlignment.end,. Then you can make one of the children of your Wrap() a Column() that has a SizedBox() as the lowest child, with the height that you need to make it appear like your texts are using the does-not-exist WrapCrossAlignment.baseLine
Example of the problem:
Example of the solution as outlined above (I did point out that it's kind of hacky):
The Code:
class WrapBaselineHackWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return DecoratedBox(
decoration: BoxDecoration(border: Border.all(color: Colors.red)),
child: Wrap(
crossAxisAlignment: WrapCrossAlignment.end,
spacing: 8,
children: [
Text(
'\$50,000.00',
style: TextStyle(fontSize: 24),
),
Column(
children: [
Text('Is a lot of money'),
//this is needed because Wrap does not have WrapCrossAlignment.baseLine
const SizedBox(height: 3),
],
),
],
),
);
}
}
Keep using Row and simply wrap Text widget with Expanded or Flexible widget.

Flutter: Left align expanded widgets

I am trying to get some text left aligned and fitting to a single row, with the last part being kept in it's original form. Something like the following:
// Original
A really long name which would wrap / Yesterday
// Output
A really long name... / Yesterday
The code below works for the above example, but:
// Original
Short Name / Yesterday
// Required Output (all left aligned)
Short Name / Yesterday
// Actual Output
Short Name / Yesterday
Is there a way to achieve that? The code below is correctly shortening the left-hand component but alignment is off.
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
ListTile(
leading: CircleAvatar(
backgroundColor: Colors.blue,
child: Text('AB'),
),
title: Text('Some text',
overflow: TextOverflow.ellipsis, maxLines: 1),
subtitle: Row(children: <Widget>[
Container(
child: Text('Person Name,
overflow: TextOverflow.ellipsis, maxLines: 1)),
Expanded(
flex: 1,
child:
Text(' / Yesterday'))
]),
),
]);
I met the same problem and finally I found a solution.
Put your "A really long name which would wrap" text into Flexible() instead of Expanded().
This will make your text get free spaces only when needed. So when your text content is not long enough, it won't take all spaces.
Just add the mainAxisAlignment property and set it to mainAxisAlignment.spaceBetween. This will space out your container and Text. Just remove the flex property from the expanded widget. It already defaults to 1.

Why is this icon being clipped?

As you can see, the face icon on the right is being clipped and I'm not sure why.
Here is my code:
new Container(
padding: new EdgeInsets.fromLTRB(style.wideMargin, style.wideMargin * 2,
style.wideMargin, style.wideMargin),
decoration: new BoxDecoration(backgroundColor: Colors.white),
child: new Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
new Expanded(
child: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
new PrecisionTextOverflow(
'Name of a thing',
lineWidth: style.longLineWrappingWidth,
mainTextStyle: style.blackParagraphText),
// Because PrecisionTextOverflow paints itself directly, the UI
// doesn't know its size so we use a blank Text object to make the
// column center itself correctly.
new Text(' '),
],
),
),
new Transform(
transform:
new Matrix4.translationValues(0.0, -style.defaultMargin, 0.0),
child: new IconButton(
padding: EdgeInsets.zero,
icon: new Icon(Icons.face,
size: style.headingText.fontSize,
color: style.favoriteColor[isItemFavorite]),
onPressed: favoritePressed,
),
),
],
),
)
That PrecisionTextOverflow is a class I made of a StatelessWidget that uses a CustomPainter to paint text on the screen. I don't imagine it's related to the issue at hand, but just FYI.
I've tried removing the padding from the outer container but it doesn't help. I've tried adjusting the transformation to shift the icon to the left but it just shifts it in its clipped form. What am I doing wrong? How can I correct this?
Edit:
Okay, I did a render tree dump and it looks like the enclosing Row sets its height as 24.0, which passes on down to the IconButton which gives itself a size of (24.0, 24.0). Is there a way to increase the height of a Row? Or should I rethink my whole structure?
You're setting the size on the Icon, rather than the IconButton. If you move the size argument to IconButton it should work.
What's going on is that the IconButton is defaulting to 24.0, and since you have it in an unbounded space it's being size-limited to 24.0 via a LimitedBox. It then tries to pass that size down to the Icon via an IconTheme inherited widget, but the Icon has been told to ignore that and be size 30.0 regardless.
I'll improve the docs.
I had the same problem for a different reason
Wrapping the IconButton in a Container with a fixed height and width can cause it to clip like in the example.