How to crop text depending on available space?
There's a similar question here, but there's no working answer.
Currently, this code
return new GridTile(
child: new Card(
elevation: 3.0,
child: new Container(
padding: new EdgeInsets.all(10.0),
child: new Column(
children: <Widget>[
Text(
document['title'],
style: new TextStyle(fontWeight: FontWeight.bold),
),
Text(
document['text'],
),
],
),
),
)
);
Gives this result:
I tried using overflow: TextOverflow.ellipsis, but the text becomes 1 line long. Specifying the text line length is a bad idea, because on different screen sizes results will vary.
How to make so that the text crops, fits or wraps itself into available space?
Setting overflow behavior should do
new Text(
widget.text,
// softWrap: true,
overflow: TextOverflow.fade,
)
See also Flutter: How to hide or show more text within certain length
Wrap the text widget Inside Expanded or Flexible widget and use overflow.ellipsis this worked for me
Column(
children: <Widget>[
Flexible(
child: Text(
"Some Very long Text or random generated strings ",
overflow: TextOverflow.ellipsis,
softWrap: true,
),
),
],
),
Try it:
extension StringX on String {
String get overflow => Characters(this)
.replaceAll(Characters(''), Characters('\u{200B}'))
.toString();
}
Text(
textString.overflow,
overflow: TextOverflow.ellipsis,
maxLines: 1,
)
It works for me.
source: https://github.com/flutter/flutter/issues/18761#issuecomment-812390920
Related
I have the following widget. The problem is I need to cut my subtitle string depending on the height and width of the ListTile. Now, height of the ListTile depends on length of substring I have. Longer is my substring, longer is the height of the ListTile. It looks awkward. Putting ListTile inside Container widget is good, but the substring overlaps the next ListTile content. it looks terrible too. Another solution was using FittedBox, I thought. But, I need the fixed size of each ListTile, without changing the fontSize. That's why the FixedBox doesn't fit me:) It changes the fontSize. I need to cut my string when it reaches the end of the ListTile. How can I solve this?
InkWell(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => ProductScreen(product),
),
);
},
child: Column(
children: [
Container(
padding: const EdgeInsets.symmetric(
vertical: 8.0,
horizontal: 4.0,
),
child: ListTile(
title: Text(
product.title.toUpperCase(),
style: Styles.listTitleStyle,
),
subtitle: Text(
product.description,
style: Styles.listBodyStyle,
),
),
),
const Divider(height: 1.0),
],
For your text widget add something like this,
subtitle: Text(
maxLines: 2, //customize your number of lines
overflow: TextOverflow.ellipsis, //add this to set (...) at the end of sentence
product.description,
style: Styles.listBodyStyle,
),
Many variations of this question exist with solutions. I have been unable to find an adequate solution. Is it possible to fix a button at the bottom of the screen which the keyboard is allowed to overlay, but also moves the other text fields up?
I've attached a screenshot example
My current solution works, but the space between the textfield and the post button is a fixed SizedBox height. This shifts the post button around on different screen heights, which is hack.
Is there a way to do something similar to how an Expanded widget fills the empty space, but within a ListView? Expanded throws an error if parent is a ListView, and a parent of Flex would squeeze all the elements when the keyboard comes up.
Widget Layout: (super simplified)
return ListView(
children: <Widget>[
Container(//The photo boxes at top
height: fixed,
),
ListTile(
leading: CircleAvatar(),
title: Container(child: TextField(),),
),
SizedBox(
height: screenHeight * 0.5 - 225
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
child: RaisedButton(
onPressed: doThing
child: Text('POST'),
),
),
],
),
],
);
I'm building a screen which has a bottom navigation bar, where I placed an burger action button and a floating button, and an appbar where I want to place my app logo.
Even though i didn't give any action to the appbar, the burger icon still appears at the left of the title.
I would like to only have the title in the appbar.
This is my code:
appBar: new AppBar(
title: new Image.asset('assets/logo/logo-home.png', fit: BoxFit.fitHeight),
actions: null,
backgroundColor: Colors.black,
elevation: 0.0,
),
key: _scaffoldKey,
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: FloatingActionButton(
child: ImageIcon(new AssetImage("assets/icons/star.png"), color: Colors.black),
backgroundColor: Colors.white,
onPressed: scan,
),
bottomNavigationBar: BottomAppBar(
color: Color.black,
child: new Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(icon: Icon(Icons.menu), color: Colors.white, onPressed: ()=> _scaffoldKey.currentState.openDrawer(),),
],
),
),
If the scaffold has a drawer and the appbar doesn't contain 'leading' property (or with null value), Appbar will append a menu icon in its actions.
It's mentioned in the documents:
If the leading widget is omitted, but the AppBar is in a Scaffold with a Drawer, then a button will be inserted to open the drawer. Otherwise, if the nearest Navigator has any previous routes, a BackButton is inserted instead. This behavior can be turned off by setting the automaticallyImplyLeading to false. In that case a null leading widget will result in the middle/title widget stretching to start.
The solution is easy, just replace title property with leading in your appbar
appBar: new AppBar(
leading: new Image.asset('assets/logo/logo-home.png', fit: BoxFit.fitHeight),
actions: null,
backgroundColor: Colors.black,
elevation: 0.0,
),
In the code below, i want to make the value of "$_counter" bold. How to accomplish that?
new Text(
'You have pushed the button $_counter time${_counter > 1
? 's'
: ''}',
style: new TextStyle(fontSize: fontSize),
textAlign: TextAlign.center,
),
I want output to be something like this:
You have pushed the button 2 times
you have to use RichTextfor that
new RichText(
textAlign: TextAlign.center,
text: new TextSpan(
style: TextStyle(color: Colors.black),
children: <TextSpan>[
new TextSpan(text: 'You have pushed the button '),
new TextSpan(text: '$_counter', style: new TextStyle(fontWeight: FontWeight.bold)),
new TextSpan(text: ' time!'),
],
),
)
You can try appending Text Widgets in a row to achieve this.
final prefixText = Text('You have clicked the button');
final counterText = Text(' $_counter', style: TextStyle(fontWeight: FontWeight.bold),);
final suffixText = Text(' times');
return Scaffold(
body: Center(
child: Row(
children: <Widget>[prefixText, counterText, suffixText],
),
),
);
NOTE: Though you get the desired output using this, I think the answer of #Raouf Rahiche is more appropriate.
You can fontWeight for it.
child: new Text(
StringUtil.FORGOT_PASSWORD,
style: new TextStyle(
color: const Color(0xFF8C919E),
fontSize: 12.0,
letterSpacing: 0.3,
fontWeight: FontWeight.bold),
),
I'm Android developer learning flutter. I want my screen looks like this:
|---------------------------------|
| |
| Babe I miss you |
| |
|---------------------------------|
"Babe" and "I miss you" should be two separate elements.
With Android xml I would solve this with LinearLayout and two TextViews with weight=1 for each. What's the alternative for flutter?
P.S. I know that you can solve it with FrameLayout or with RelativeLayout but I want closest to LinearLayout behavior.
Flutter's Row widget is equivalent to android's LinearLayout with android:orientation="horizontal",
and Column widget is equivalent to android's LinearLayout with android:orientation="vertical".
flex property of Flexible widget is equivalent weight property, you can wrap the Text widgets in a Flexible widget and specify the flex property.
Example:
new Row(
children: <Widget>[
new Flexible(child: new Text("Babe"), flex: 1,),
new Flexible(child: new Text("I miss you"), flex: 1,)
],
)
Using an Expanded widget can also produce a LinearLayout effect like so:
Row(
children: <Widget>[
Expanded(
child: Container(child: Text("Babe")),
flex: 2,
),
Expanded(
child: Container(child: Text("I don't miss you"),alignment: Alignment.centerRight),
flex: 2,
),
],
),
Considering the layout in the question you want to display both the texts at the end of screen one at the beginning other at the end you can simply add MainAxisAlignment.spaceBetween property to the row
so you need to modify your code to
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
new Text('Babe'),
new Text('I miss you')
]
)
I dont understand why first answer was accepted because it simply adds both the text to right most end of the screen,
Tip: Incase you need some padding around each text wrap each of the text in a Container and add desired padding and margin
You can use row with MainAxisAlignment which will allow you to place elements as per your expectation
Widget textSection = new Container(
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
new Text('Babe'),
new Text('I miss you')
)
)
Screenshot:
Use Spacer which comes with a flex property (defaults to 1)
Row(
children: <Widget>[
Text('Hello'),
Spacer(), // <-- Use this
Text('World'),
],
)
new Container(
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget> [
new Text('Babe', style: AppStyle.AppBarTextStyle,),
new Text('I miss you',style: AppStyle.AppBarTextStyle,)
]
)
)
We can use FractionallySizedBox widget to give weight sum for both width and height.
FractionallySizedBox(
heightFactor: .5,
widthFactor: 1.0,
alignment: Alignment.topCenter,
child: child,
)
For more info:
Link