How does flutter make textfield dynamically display multiple lines? - flutter

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

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.

How can I keep a TextField in a single run in a Wrap until it reaches a minimum width?

Display:
Code
Card(
child: Wrap(children: [
Text('Hi. What\'s your name?'),
Container(
constraints: BoxConstraints(minWidth: 300), child: TextField())
]))
Demo
https://dartpad.dev/65527c29343bd9afca842dff66907e6f?null_safety=true
What's needed
I would like for the TextField to run adjacent to right of the Text. It should have a minimum constraint width of 300. Then if the available space to the right of the Text is less than 300, it should wrap and place itself below the text.
Basically, I need to implement similar method to Expadable for the TextField that only covers the first run of the Wrap.
Problem
The TextField automatically extends to the largest possible width.
Because this is a Wrap, it automatically sends it below the initial Text where it has the most available width.
Use Row Widget instead of Wrap and expand the text
Card(
child: Row(children: [
Expanded(child: Text('Hi. What\'s your name?')),
Container(width: 300, child: TextField())
]),
),

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 ?

How to wrap a row of texts?

I have two Text widgets inside a Row. I want to show the text widgets one after another, and wrap the second one to the next line if it doesn't fit in the first line.
I've tried Flexible, Wrap, and what not. I can't seem to get it working.
Row(
children: <Widget>[
Text('This is some text.'),
Text('Another piece of text.')
]
);
I want the output to look something like this (the screen edges are indicated by |):
|This is some text. Another |
|piece of text. |
The best I could get was the following:
|This is some Another piece|
|text. of text. |
Edit: Thanks for replies, everyone. I've tried RichText too, and it works, but I want to bind more than one gesture to each TextSpan element, which cannot be done easily with RichText. I'm about to create a question on that, but stackoverflow doesn't allow me to create more than one question in 90 minutes.
UPDATED ANSWER
The first thing you are doing wrong is using Row to put one text widget under another text.
|This is some text. Another |
|piece of text. |
This is the desired UI are you are trying to achieve right? So From your question, it is clear that you want two text widget one under another.
so this code will work for you. replace Row with Column widget like this. If you want to continue with Row each of your text will wrap but not one text after another. here is the working code. I have putted two text to show you that how they wrap one after another. Checkout the image below to see the result
body: Center(
child: Container(
color: Colors.amberAccent,
width: 200,
height: 200,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: <Widget>[
Flexible(
fit: FlexFit.tight,
child: Text(
'This is some text.long text more long Text, even more long text',
style: TextStyle(color: Colors.white, fontSize: 20.0),
),
),
Flexible(
fit: FlexFit.tight,
child: Text(
'Another piece of text.not so long text yet needs to be a liitle long text',
style: TextStyle(color: Colors.white, fontSize: 20.0),
),
)
],
),
),
),
),
here is the screenshot
The Wrap Widget will either keep the two Texts on the same line or put the second Text on the next line if there's overflow.
Wrap(
children: [
Text(
'This is some text.',
),
Text(
'Another piece of text.',
),
],
),
You can achieve that using the RichText widget:
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey,
appBar: AppBar(),
body: RichText(
text: TextSpan(
children: [
TextSpan(text: "This is some text."),
TextSpan(text: "Another piece of text. Another piece of text. Another piece of text. Another piece of text."),
],
),
),
);
}
The RichText widget displays text that uses multiple different styles.
The text to display is described using a tree of TextSpan objects,
each of which has an associated style that is used for that subtree.
The text might break across multiple lines or might all be displayed
on the same line depending on the layout constraints.
RichText

Expand Textfield if available space, set minHeight with scroll if not

I've got a Column indide a Scaffold, and one of the Column's children is a TextField. I'd like the Textfield to expand and take all the available space, but if there is not enough space (basically when the keyboard shows up), I want the Textfield to be 3 lines height min and the Column to be scrollable so the focus on the Textfield works as intended.
I've tried a lot of different widgets, like Expand, IntrinsicHeight, LayoutBuilder, ConstrainedBox, SingleChildScrollView...
But none of the tested combination did work as expected...
The SingleChildScrollView page did help me a lot but none of the example match my situation :
https://docs.flutter.io/flutter/widgets/SingleChildScrollView-class.html
Scaffold(
body: Column(
children: <Widget>[
Text("Some\nvery\nvery\nvery\nvery\nvery\nvery\nvery\nvery\nvery\nvery\nvery\nlong\ntext"),
RaisedButton(child: Text("Some button")),
Text("Second line"),
Expanded(
child: Padding(
//Use the expand parameter instead of padding + maxLines, once released : https://github.com/flutter/flutter/pull/27205
padding: const EdgeInsets.only(top: 10, bottom: 30),
child: TextField(
decoration: InputDecoration(
hintText: "Message...",
),
maxLength: 500,
maxLengthEnforced: true,
maxLines: 50,
),
),
),
Center(
child: RaisedButton(
child: Text('OK'),
onPressed: _send,
),
)
],
),
)
With that code the first part works fine : when not keyboard is shown, the Textfield is expanded as expected.
But when the keyboard shows up, the layout overflow (because there is no SingleChildScrollView).
EDIT : the new TextField.extends property helped a bit but didn't solved my issue...