Flutter - How to show text and icon in one line in row? - flutter

I am using row widget with three child widgets:
Text
Icon
Text
I want all of them to appear in single line same level horizontally and drop to new line if text increases.
I am using below code for Row widget but last Text widget is not aligned correctly
The text dropping should start below the "Tap" and "on the right hand" is not aligned
Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
'Tap ',
style: TextStyle(
fontSize: 17,
),
),
Icon(Icons.add),
Expanded(
child: Text(
'on the right hand corner to start a new chat.',
style: TextStyle(
fontSize: 17,
),
),
)
],
)

Use Text.rich with WidgetSpan to put icon inside text (inline)
Text.rich(
TextSpan(
style: TextStyle(
fontSize: 17,
),
children: [
TextSpan(
text: 'Tap',
),
WidgetSpan(
child: Icon(Icons.add),
),
TextSpan(
text: 'on the right hand corner to start a new chat.',
)
],
),
)

Flutter has WidgetSpan() to add a widget inside the RichText().
RichText(
text: TextSpan(
children: [
TextSpan(
text: "Click ",
),
WidgetSpan(
child: Icon(Icons.add, size: 14),
),
TextSpan(
text: " to add",
),
],
),
)
Above code will produce:
Click > to add
You can treat the child of WidgetSpan like the usual widget.

You need put sinlein line crossAxisAlignment: CrossAxisAlignment.start inside
Row
Row (
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Icon(Icons.add, size: 14),
Expanded(
child: Text("your multiline text "),
),
),
],
)

Related

TextSpan's text doesn't show if it overflows

That's how it looks when I have a WidgetSpan and a TextSpan, and the text inside the TextSpan is too long:
problem
A similar question has already been asked here TextSpan's text doesn't show if it overflows and is placed after WidgetSpan, but the one answer isn't suitable for my problem.
I have two Text.rich() widgets (which each host one WidgetSpan and one TextSpan) inside an Expanded widget, both Expanded with flex:1, because I want them to be the same size and take as much space as they can. That's why a row is not an option, you can't (as far as I know) put two rows side by side, at this happens...
using rows
This is how it's supposed to look like, just with the TextOverflow.ellipsis, if the text is too long:
target UI
Here is my code:
Row(
children: [
Expanded(
flex: 1,
child: Text.rich(
TextSpan(children: [
WidgetSpan(
child: Container(
margin: const EdgeInsets.only(right: 4.0),
child: SvgPicture.asset("assets/icons/building.svg", color:
htLightGrey),
),
),
TextSpan(
text: incident.building.name,
style: const TextStyle(
fontWeight: FontWeight.normal,
fontSize: 16.0,
color: htLightGrey, /*overflow: TextOverflow.ellipsis*/
),
),
]),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
Expanded(
flex: 1,
child: incident.department != null
? Text.rich(
TextSpan(children: [
WidgetSpan(
child: Container(
margin: const EdgeInsets.only(right: 4.0),
child: SvgPicture.asset("assets/icons/department.svg",
color: htLightGrey),
),
),
TextSpan(
text: incident.department!.name,
style: const TextStyle(fontWeight: FontWeight.normal,
fontSize: 16.0, color: htLightGrey, overflow:
TextOverflow.ellipsis),
),
]),
maxLines: 1,
overflow: TextOverflow.ellipsis,
)
: const SizedBox.shrink(),
)
],
)
To achieve your target Ui, use the Wrap widget instead of the Row widget. Here, when the contents of the widget overflow/exceed it will break it to the next line, hence you'll achieve your target Ui.
While we like to archive this UI, we are using Row as parent widget, which is perfect. Then we can split the row into tree part, left two part will get same and maximum available width. For this scenario, widget structure as follows.
Row(
mainAxisSize: MainAxisSize.min,
children: [
Expanded(
flex: 1,
child: Container(
color: Colors.green,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start, //start from left
children: [
buildItem(
text:
"incident.buildi cident.buildi cident.buildi cident.buildi cident.building.name"),
buildItem(text: "incide ing.ssss"),
],
),
),
),
Expanded(
flex: 1,
child: Container(
color: Colors.red,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
buildItem(text: "i ent.building.name"),
buildItem(text: "incident.building.ssss"),
],
),
),
),
IconButton(
onPressed: () {},
iconSize: 33,
icon: Icon(Icons.arrow_right),
),
],
),
And inside Text.rich add use alignment: PlaceholderAlignment.middle, on WidgetSpan to set the middle.
maxLines: 1,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.start,
And you will get
I am using extra container to point the UI, simply remove the container from the column. Also, you can use Row instead of Rich Text.
Test widget
class _TestGroundState extends State<TestGround> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Row(
mainAxisSize: MainAxisSize.min,
children: [
Expanded(
flex: 1,
child: Container(
color: Colors.green,
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start, //start from left
children: [
buildItem(
text:
"incident.buildi cident.buildi cident.buildi cident.buildi cident.building.name"),
buildItem(text: "incide ing.ssss"),
],
),
),
),
Expanded(
flex: 1,
child: Container(
color: Colors.red,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
buildItem(text: "i ent.building.name"),
buildItem(text: "incident.building.ssss"),
],
),
),
),
IconButton(
onPressed: () {},
iconSize: 33,
icon: Icon(Icons.arrow_right),
),
],
),
],
));
}
Text buildItem({
required String text,
}) {
return Text.rich(
TextSpan(
children: [
WidgetSpan(
alignment: PlaceholderAlignment.middle,
child: Container(
child: Icon(Icons.ac_unit),
),
),
TextSpan(
text: text,
style: TextStyle(
fontWeight: FontWeight.normal,
fontSize: 16.0,
),
),
],
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.start,
);
}
}
More about flutter layout

Flutter. Row with MainAxisAlignment.spaceBetween overflowed

I am new in flutter and I'm trying to implement screen like this:
As you can see I need to make something like a table. I ran into a problem while implementing table rows. Here is my code:
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text("2.", ),
const SizedBox(width: 10),
Text(text: "This is second with very long text"),
],
),
),
const SizedBox(width: 8),
Text("500"),
],
),
But I'm getting the error:
A RenderFlex overflowed by 42 pixels on the right.
For some reason my text ("This is second with very long text") doesn't move to a new line, but goes off screen.
Please tell me what am I doing wrong?
You have to wrap your Text("This is second with very long text") widget inside Flexible widget like this:
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text("2."),
const SizedBox(width: 10),
Flexible(
child: Text("This is second with very long text"),
),
],
),
),
const SizedBox(width: 8),
Text("500"),
],
),
Just use a ListTile for that.
ListTile(
leading: Text("2. "),
title: Text("This is second with very long text"),
trailing: Text("500"),
)
This is much simpler to implement and handles long text automatically.
You can set padding etc as you wish. You can find more information about list tiles in the official documentation.
you need a Column, to wrap the widgets inside, inside the column you need a first Row that will hold the first and second,
then a HorizontalLine, and then the rest of the rows:
Please, see the example below
Container(
padding: EdgeInsets.all(10),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
//first row:
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('First', style: TextStyle(color: Colors.black, fontWeight: FontWeight.bold)),
Text('Second', style: TextStyle(color: Colors.black, fontWeight: FontWeight.bold)),
]
),
//This SizedBox gives space between widgets
SizedBox(height:5),
Container(color: Colors.black, height: 2, width: double.infinity),
//This SizedBox gives space between widgets
SizedBox(height:5),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('1', style: TextStyle(color: Colors.black, fontWeight: FontWeight.bold)),
//In order to make the Text multi-lined you need to wrap-it into a SizedBox widget
SizeddBox(
//as I can see, the middle text widget is almost the 70% of the total width
//You can get the total width from MediaQuery.of(context).size.width
width: MediaQuery.of(context).size.width * 0.7,
child: Text('This is first', style: TextStyle(color: Colors.black)),
),
Text('500', style: TextStyle(color: Colors.black, fontWeight: FontWeight.bold)),
]
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('2', style: TextStyle(color: Colors.black, fontWeight: FontWeight.bold)),
//In order to make the Text multi-lined you need to wrap-it into a SizedBox widget
SizeddBox(
//as I can see, the middle text widget is almost the 70% of the total width
//You can get the total width from MediaQuery.of(context).size.width
width: MediaQuery.of(context).size.width * 0.7,
child: Text('This is second with a very long text', style: TextStyle(color: Colors.black)),
),
Text('12', style: TextStyle(color: Colors.black, fontWeight: FontWeight.bold)),
]
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('3', style: TextStyle(color: Colors.black, fontWeight: FontWeight.bold)),
//In order to make the Text multi-lined you need to wrap-it into a SizedBox widget
SizeddBox(
//as I can see, the middle text widget is almost the 70% of the total width
//You can get the total width from MediaQuery.of(context).size.width
width: MediaQuery.of(context).size.width * 0.7,
child: Text('This is third with a long text too', style: TextStyle(color: Colors.black)),
),
Text('150', style: TextStyle(color: Colors.black, fontWeight: FontWeight.bold)),
]
),
]
)
In this code, you can change the styling and etc as you wish.
I would suggest you to extract the the Row widget that holds the number, the text and the score in a Stateless widget, or in a method that returns Widget object, but it's very soon for this.
I hope I helped you.
Enjoy Flutter!

I want to align the starting place of two texts

I have one "row" and two "text" widgets inside. I want to align the starting place of two texts. ie "m. name" and "m105" should line up.
Container(
child: Row(
children: [
Container(
child: Align(
alignment: Alignment.topLeft,
child: Text(
"M. Adı: ",
style: TextStyle(fontWeight: FontWeight.bold),
),
),
),
// SizedBox(
// width: 20,
// ),
Expanded(
child: Text(
"$productName",
overflow: TextOverflow.ellipsis,
maxLines: 3,
softWrap: true,
),
),
],
),
),
Try
Row() widget attribute
crossAxisAlignment: CrossAxisAlignment.start
Text() widget attribute
textAlign: TextAlign.start,
/// Try something like that
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"M. Adı: ",
style: TextStyle(fontWeight: FontWeight.bold),
),
),
SizedBox(width: 5),
Flexible(
child: Text(
"$productName",
textAlign: TextAlign.start,
),
),
],
),
Add crossAxisAlignment: CrossAxisAlignment.center, to your Row widget it should be aligned as you desired or still if it doesnt works just try changing center with other values check which one works for you...
and even after adding above property to your Row widget then you would have to remove alignment of topleft in your text of m.name

How to justify text in a flutter column widget?

I would like to align left elements vertically and same with right one with padding, here is what I got as a result, the elements are not aligned and I cannot insert padding in the second row so that left elements are aligned
return InkWell(
child: Column(
children: <Widget>[
Row(
children:<Widget> [
Padding(padding:EdgeInsets.fromLTRB(18.0, 0.0, 0.0, 0.0)),
Text(
product.libelle,
style: theme.textTheme.title,
maxLines: 1,
textAlign: TextAlign.left,
),]),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children:<Widget> [
Text(
product.description,
style: theme.textTheme.subtitle,
maxLines: 1,
),
RaisedButton( onPressed: () {},
child: new Text("S\'abonner"),
)
]),
),
);
Use Text Widget and TextAlign.justify :)
Text('my String', textAlign: TextAlign.justify),
Text( 'Vinay',
**textAlign: TextAlign.justify,**
style:TextStyle() ),
incase of Rich Text
RichText(
**textAlign: TextAlign.justify,**
text: TextSpan( style: TextStyle(color: Colors.black, fontSize: 36),
children: <TextSpan>[
TextSpan(text: 'Woolha ', style: TextStyle(color: Colors.blue)),
TextSpan(text: 'dot '),
TextSpan(text: 'com', style: TextStyle(decoration: TextDecoration.underline))]))
Would you try to wrap second row with Padding widget?
Padding(
padding: EdgetInsets.symmetric(horizontal: 18.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children:<Widget> [
Text(
product.description,
style: theme.textTheme.subtitle,
maxLines: 1,
),
RaisedButton( onPressed: () {},
child: new Text("S\'abonner"),
)
]),
)
Your top level widget should be a Row, since you want to horizontally position your widgets next to each others. So what you should do instead is use the following structure (pseudocode):
Row
Column
Text (title)
Text (subtitle)
Button
It's also important to use the correct alignment properties (MainAxisAlignment.spaceBetween on Row so that there is a space between the two main elements and CrossAxisAlignment.start + MainAxisAlignment.center on Column to center things).
I created a pen to demonstrate it: https://codepen.io/rbluethl/pen/QWyNQjE
Hope that helps!
Please try this
Just add below 2 line of code inside you Column Widget.
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,

Flutter Align both texts at the start Vertically in a row

I'm a little stumped here but i'm trying to align two text widgets at the vertical start in a row in Flutter but no matter what I try to do the text is centred in the text widget with less text. I'm trying to get the 'Address' title and the actual address to both start at the top vertically in the row but because the actual address is longer it always centres the Address title (in below image address is centred in the first job in the list).
This is the code that I am using:
Column(children: <Widget>[
Row(children: <Widget>[
Text('Status: ', style: TextStyle(fontWeight: FontWeight.bold),),
Text(job['status'])
],),
Row(children: <Widget>[
Text('Engineer: ', style: TextStyle(fontWeight: FontWeight.bold),),
Flexible(child: Text(job['eng']))
],),
Row(mainAxisAlignment: MainAxisAlignment.start, children: <Widget>[
Text('Address: ', style: TextStyle(fontWeight: FontWeight.bold),),
Flexible(child: Text(job['address']))
],)
],)
I've tried to mainaxisalignment.start on the row but its not working...any ideas anyone?
Try crossAxisAlignment: CrossAxisAlignment.start on your Row
I'm not sure i understand what exactly do you want to do but maybe you want to use Column instead of Row for Address with crossAxisAlignment
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Address: ',
style: TextStyle(fontWeight: FontWeight.bold),
),
Text(job['address'])
],
)
or maybe
Row(
children: <Widget>[
Flexible(
child: RichText(
text: TextSpan(
text: 'Address: ',
style: TextStyle(
fontWeight: FontWeight.bold, color: Colors.black),
children: [
TextSpan(
text: '23 Test Street, Test City',
style: TextStyle(
fontWeight: FontWeight.normal,
color: Colors.black),
),
],
),
),
),
],
)