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.
Related
I'm trying to put an image inside a long text being wrapped in a Dart AlertDialog() widget. Let me illustrate the problem with some images.
What I want:
What I want
What I have:
What I have
(The coin Image() is flushed to the line after my text while I want it being part of it).
I'm currently trying to use the Wrap() widget, see the minimal code below
Wrap(children: [
Flexible(
child: Text('Are you sure you want to buy this item for ' +
item.price.toString())),
Padding(
padding: const EdgeInsets.fromLTRB(5, 0, 0, 5),
child: Image.asset(
"path/to/my/image",
width: 30,
)),
Text('?'),
]),
It is supposed to place its children's widgets below each other when reaching the width of the Wrap() context. However, it's not working as I would like, since it put the Image widget below the Text() one being wrapped by Flexible() instead of putting it next to this last.
My opinion about this problem is that the wrapping of a text line still creates a "text box" that will go until the end of the context width (i.e. the end of the line) even if the last line of text stops earlier. This is due to the fact that the previous line had obviously reached the width of the Wrap() context. This is probably why the Image.assets() inserted as the next widget in the Wrap() children list is flushed to the next line anyway.
Of course I've tried several other approaches, namely to use the Row() widget with the Text() widget wrapped inside a Flexible() widget as follow:
Row(children: [
const Flexible(
child: Text(
'Are you sure you want to buy this item for ' + item.price.toString(),
)),
Row(children: [
Padding(
padding: const EdgeInsets.fromLTRB(5, 0, 0, 5),
child: Image.asset(
"path/to/my/image",
width: 30,
)),
Text('?'),
]),
Which of course does not work since it places the Image() widget not next to the last word of the wrapped text but next to the whole generated Flexible() text zone.
Of course, the problem comes with the fact that the text is long and is, therefore, broken into several lines. The first approach would have worked perfectly if the text was not broken into several lines.
Is there any way to either
Limit the size of a wrapped line in order to avoid it being considered as a full line when wrapped;
Insert an image as a text character so that only the use of Flexible() do the trick to solve this problem;
Break a row widget into several lines automatically.
Thanks in advance for your time
Try Text.rich:
Text.rich(TextSpan(
children: <InlineSpan>[
TextSpan(text: 'Flutter is'),
WidgetSpan(
child: Padding(
padding: const EdgeInsets.fromLTRB(5, 0, 0, 5),
child: Image.asset(
"path/to/my/image",
width: 30,
),),),
TextSpan(text: '?'),
],
)
I think the text widget extends to the end of the line which prevents the image from getting behind. To solve this problem I propose to split the first sentence into two blocks of text like this:
Wrap(children: [
Flexible(
child: Text('Are you sure you want to')),
Flexible(child: Text('buy this item for ' )),
Padding(
padding: const EdgeInsets.fromLTRB(5, 0, 0, 5),
child: Image.asset(
"path/to/my/image",
width: 30,
Text('?'),
]),
Other way is to look on the way of Stack widget which seem to be a good solution
How to set the length of the overflow: TextOverflow.ellipsis becuase it truncate the text as you see in img. There is a empty space between the text 'This is the first...' and the nummber '#1520'. The overflow truncates the text after 'first...' word.
I want that the words 'card now' will be shown in the Row. How to fix it?, thanks
Container(
color: Colors.grey,
child: ListTile(
title: Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(child: Text('This is the first card now its time sad sad sad sads ad sdsadsads dsa dsad asdasdasd', overflow: TextOverflow.ellipsis, style: TextStyle(color: Colors.white),)),
Flexible(child: Text('#1520', overflow: TextOverflow.ellipsis, style: TextStyle(color: Colors.white),)),
],
),
),
),
),
I dont want all of my text to be visible, I just want to show some words in one line. If you look at the img, you will see an empty space between the text and the #1520. I want to use overflow and show: This is the first card now.. #1520
If you want all of your text to be visible just remove overflow property from the text widget.
If you want to limit your text to certain lines then add the maxLines property with overflow. like this
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Flexible(child: Text("This is the first card now its time sad sad sad sads ad sdsadsads dsa dsad asdasdasd", maxLines: 2, overflow: TextOverflow.ellipsis,)),
Flexible(child: Text("#1520"))
],
),
This is the default behaviour of how Text widget works with overflowing - it will truncate sentences with words if it detects the text width is greater than the width it can take. Because of this, sometimes it will cause the unexpected extra space between the truncated text and the container edge.
Here is a simple solution if you don't mind part of a word is covered:
simply apply softWrap: false to your text widget.
Text(
'Long long long long long long text text text text text',
softWrap: false,
maxLines: 1,
overflow: TextOverflow.fade,
)
I am using Flutter programming. I need to display a title and a button next to the title. If the text length is less button also should display next to the text. If text length is more i want to fix the text length as maximum 200px and need to show the button next to the title.
I am using the below code. And working fine with the less text length.
Problem is: If text length is more, then my button is moving out of screen. You can see the behaviour in the below attached image.
Row(
children: <Widget>[
Container(
child: RichText(
overflow: TextOverflow.ellipsis,
strutStyle: StrutStyle(fontSize: 12.0),
text: TextSpan(
style: TextStyle(color: Colors.white), text: model.title),
),
),
Text("My Button"),
],
)
You can put maximum characters
text.substring(0,150)
I think there's no maxLength property for RichText and Text widget. If you are using RichText class, you'll have maxLines property that can be used. I tried to recreated your case and wrapped RichText widget with Flexible widget that lets the child widget to use only the minimum available space. But I wasn't able to replicate the error you mentioned. The long text I used gets ellipsis and the button doesn't go out of the screen. Note that I also used maxLines property which if you set to 2, will wrap the long text in new line without moving away the button and the long text will be shown as ellipsis. Sample working code below:
body: Center(
child: Row(
children: <Widget>[
Container(
child: Flexible(
child: RichText(
maxLines: 2,
overflow: TextOverflow.ellipsis,
strutStyle: StrutStyle(fontSize: 12.0),
text: TextSpan(
style: TextStyle(color: Colors.white), text: 'I am using Flutter programming. I need to display a title and a button next to the title. If the text length is less button also should display next to the text. If text length is more i want to fix the text length as maximum 200px and need to show the button next to the title.'),
),
)
),
Text("My Button"),
],
)
)
If you set maxLines to 1, the long text will wrap in ellipsis.
Hope this helps.
String addressText = userAddress.address.toString();
if(addressText.length > 22)
addressText = addressText.substring(0,22);
You can check length and split string if exceeds max length.
you can use Expanded or give fixed width to container of rich text, like this with Expanded widget:-
Row(
children: <Widget>[
Expanded(
child: RichText(
overflow: TextOverflow.ellipsis,
strutStyle: StrutStyle(fontSize: 12.0),
text: TextSpan(
style: TextStyle(color: Colors.white), text: model.title),
),
),
Text("My Button"),
],
)
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
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.