I am new to flutter learning a flutter UI build from youtube. While I am using the expanded widget, I found the output is not what I want, just wanna ask is there any way to limit the height of the expanded widget.
This is my current UI looks like.
SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Align(
alignment: Alignment.topRight,
child: Container(
alignment: Alignment.center,
height: 52,
width: 52,
decoration: BoxDecoration(
color: Color(0xFFF2BEA1),
shape: BoxShape.circle,
),
child: SvgPicture.asset("icons/icons/menu.svg"),
),
),
Text(
"\t\tMake Cents out of \n\t\tSolar",
style: Theme.of(context).textTheme.subtitle1!.copyWith(
fontWeight: FontWeight.w900,
fontSize: 38,
color: Colors.blueGrey[900]),
),
Padding(
padding: const EdgeInsets.all(20.0),
child: Container(
padding: EdgeInsets.symmetric(horizontal: 30, vertical: 5),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(29.5),
),
child: TextField(
decoration: InputDecoration(
hintText: "Search",
icon: SvgPicture.asset("icons/icons/search.svg"),
border: InputBorder.none,
),
),
),
),
Expanded(
child: GridView.count(
crossAxisCount: 2,
childAspectRatio: .85,
children: <Widget>[
CategoryCard(
title: "Promotion of the day",
svgSrc: "icons/icons/Hamburger.svg",
press: () {},
),
CategoryCard(
title: "Promotion of the day",
svgSrc: "icons/icons/Hamburger.svg",
press: () {},
),
],
),
),
Container(
padding: EdgeInsets.fromLTRB(20.0, 0, 0, 0),
child: Text(
"Solar Panel",
style: Theme.of(context).textTheme.subtitle1!.copyWith(
fontWeight: FontWeight.w900,
fontSize: 20,
color: Colors.black),
),
),
],
I wanna know is there any way to control the height of the expanded widget so that my container with text can connect right below the custom Category Card. Or should I use another widget instead of using the expanded widget?
By definition, the Expanded widget will fill up all the remaining screen space. If you instead want to use a set size, you can use a Container or SizedBox with their width and height parameters.
To get a better understanding of constraints in general, I suggest you check out this flutter documentation page all about constraints.
To set a minimum and maximum size (width and height) for a widget you can use ConstrainedBox widget, learn more about it here
You can't control the height of the Expanded widget. It takes all the space that is available on the screen. I suggest you to use SizedBox and explicitly provide the required height and set width as double.infinity.
I had same issue. I suggest ConstrainedBox widget to set minimum and maximum heights.
Related
I am styling a card and have these multiple icon elements and text in it. I am having issues arranging the rows and columns to solve this problem here;
Image 1
And this is what I am trying to achieve;
Image 2
Here is my code for that row giving me issues;
Row(
children: [
ClipRect(
child: Container(
height: 11,
width: 11,
child: Image.asset('assets/info.png'),
),
),
Container(
height: 48,
child: Column(
children: [
Text(
"Now that you've finished a plan, it's essential to measure your growth. We've included assessments and activities to do just that.",
style: GoogleFonts.poppins(
textStyle: TextStyle(
color: Color(0x80484848),
fontWeight: FontWeight.w400,
fontSize: 8,
),
),
),
],
),
),
],
),
I thought that text always align properly if fit into a column. I want the overflowing text to go over to the next line.
EDIT: to make the text wrap to the next line, wrap your Column with an Expanded():
Row(
children: [
ClipRect(
child: Container(
height: 11,
width: 11,
child: Image.asset('assets/info.png'),
),
),
Expanded(
child: Column(
children: [
Text(
"Now that you've finished a plan, it's essential to measure your growth. We've included assessments and activities to do just that.",
style: TextStyle(
overflow: TextOverflow.visible,
color: Color(0x80484848),
fontWeight: FontWeight.w400,
fontSize: 30,
),
),
],
),
),
],
)
To avoid an overflow, wrap your Container() with a Flexible() and your Text() with a FittedBox().
The docs on FittedBox():
Scales and positions its child within itself according to fit.
So, fittedBox will scale the font size to fit accordingly.
Your code should look like this:
Row(
children: [
ClipRect(
child: Container(
height: 11,
width: 11,
child: Image.asset(
'assets/info.png'),
),
),
Flexible(
child: Container(
height: 48,
child: Column(
children: [
FittedBox(
child: Text(
"Now that you've finished a plan, it's essential to measure your growth. We've included assessments and activities to do just that.",
style: TextStyle(
color: Color(0x80484848),
fontWeight: FontWeight.w400,
fontSize: 30,
),
),
),
],
),
),
),
],
)
Result (notice the text size scales):
As an alternative, you can also use a TextOverflow instead of FittedBox() which will add an ellipsis (...) to the overflowing text:
Row(
children: [
ClipRect(
child: Container(
height: 11,
width: 11,
child: Image.asset(
'assets/info.png'),
),
),
Flexible(
child: Container(
height: 48,
child: Column(
children: [
Text(
"Now that you've finished a plan, it's essential to measure your growth. We've included assessments and activities to do just that.",
style: TextStyle(
overflow: TextOverflow.ellipsis,
color: Color(0x80484848),
fontWeight: FontWeight.w400,
fontSize: 30,
),
),
],
),
),
),
],
)
Result (notice the elipsis):
I am trying to spaceevenly an Icon() and a AutoSizeText() in a Row().
When the amount is long as you can see in the attached images it renders as expected, but when the amount is zero or pretty short, the AutoSizeText() is being centered, but this causes that the same distance from the edges is no longer maintained. There is an extra distance caused by the centering. I do not know how to fix this.
Edit. If it wasn't clear, I'm referring to the pink shopping bag icon and the amount showed in the "Riepilogo Settimanale" section. If you look at the Restaurant Icon and its amount, you can notice how they are not centered, they are closer to the left edge.
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
),
width: size.width * 0.3,
height: size.height,
// height: size.height * 0.055,
child: Row(
children: [
Spacer(),
Expanded(
flex: 3,
child: Container(
child: LayoutBuilder(
builder: (context, constraint) {
return Icon(
icona,
color: colore,
size: constraint.biggest.width * 1,
);
},
),
),
),
Spacer(),
Expanded(
flex: 6,
child: Center(
child: AutoSizeText(
importo,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: colore,
),
maxLines: 1,
),
),
),
Spacer(),
],
),
)
If I understood you correctly, you want to right-align the text, not center them.
To achieve that, consider using a single Spacer() in-between the icon and the text. The outside spacing (margin and padding) can be done using Padding widget instead.
I have a Container widget in which all my codes are in for the particular page. It has a background image and inside the container, there is a Center widget. I want to set the background color of the center widget to white but while doing so, the entire screen's background is changing to white. How can I achieve that please?
return Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('Assets/images/loginbg2.jpg'),
fit: BoxFit.cover
),
),
child: Scaffold(
backgroundColor: Colors.transparent, //code for background image
body: Center(
child:Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Align(
alignment: Alignment.topLeft,
child: Padding(
padding: EdgeInsets.fromLTRB(40, 0, 0, 0),
child: Text(
"Welcome back!",
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
)
),
SizedBox(
height: 20.0,
), //code for center widget
This is probably because the Column widget inside your Center widget is taking up the entire screen.
A Column widget (unless constrained) is taking up all the space it can get.
Try solving your issue by removing the Column widget for now and only use the container inside the Center widget and define it's height and width. See if the background you want is coming back in view.
All I need is my text to be multi-line. Am giving the property of maxLines but its still getting RenderFlex overflowed error to the right as the next is not going to 2nd line,
Align( alignment: Alignment.bottomCenter,
child: new ButtonBar(
alignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.all(20.0),
child: new Text(
"This is a very bigggggggg text !!!",textDirection: TextDirection.ltr,
style: new TextStyle(fontSize: 20.0, color: Colors.white),
maxLines: 2,
),
)
],
),
)
Short answer
All that is required for multi-line text, is that your Text() widgets' width is limited by a parent widget. For example:
SizedBox(
width: 150,
child: Text(
"This text is very very very very very very very very very very very very very very very very very very very very very very very very very long",
),
),
Long answer
Minimal working example + explanation:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold( //Text widgets, multi-line or not, need a Scaffold widget somewhere up the widget tree.
body: Row( //Widgets which help to display a list of children widgets are the 'culprit', they make your text widget not know what the maximum width is. In OP's example it is the ButtonBar widget.
children: [
Container(
width: 100, //This helps the text widget know what the maximum width is again! You may also opt to use an Expanded widget instead of a Container widget, if you want to use all remaining space.
child: Center( //I added this widget to show that the width limiting widget doesn't need to be a direct parent.
child: Text(
"This text is very very very very very very very very very very very very very very very very very very very very very very very very very long",
),
),
),
],
),
),
);
}
}
Extra
You also mentioned maxlines. This property limits the
maximum amount of lines. If this is what you want, I recommend you also play with the overflow property.
SizedBox(
width: 100,
child: Text(
"This text is very very very very very very very very very very very very very very very very very very very very very very very very very long",
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
),
UPDATE
I came across this video on the official Flutter channel which explains this issue quite well. They recommend using a LimitedBox widget.
Just wrap your text widget with Expanded as below
Expanded(
child: Text('data', maxLines: 4,
overflow: TextOverflow.ellipsis,
textDirection: TextDirection.rtl,
textAlign: TextAlign.justify,),
),
try this:
Expanded(
child: Text(
'a long text',
overflow: TextOverflow.clip,
),
),
in my implementation I put this inside a row and surrounded it with sized boxes on each side so that I have some space between my elements, why using expanded you may ask, well it's used to take as much space as possible so the text would look good in portrait or landscape mode.
and here is a full example on how to make it even react vertically not just horizontally:
Card(
child: InkWell(
onTap: (){},
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: <Widget>[
SizedBox(
height: 70, // default\minimum height
),
Container(
height: 44,
width: 44,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.all(Radius.circular(22))),
),
SizedBox(
width: 15,
),
Expanded(
child: Text(
'the very long title',
overflow: TextOverflow.clip,
),
),
SizedBox(
width: 10,
),
Text(
'value', //some other text in the end of the card or maybe an icon instead
),
SizedBox(
width: 30,
),
],
),
),
),
)
I think you forgot to add overflow type.
You can use something like this:
Text(
"TOP ADDED",
textAlign: TextAlign.justify,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 18.0),
maxLines: 2,)
Use Expanded widget with column to achieve multiline text.
Expanded(child:
Column(crossAxisAlignment: CrossAxisAlignment.start ,
children: [
Text(food.title),
Text(food.price)
]
))
Just wrap the text widget in Flexible. As it only use space that it need.
After maxLines, it just cut to ellipsis.
If you want unlimited lines, just remove maxLines attribute. With the help of Flexible, it uses space which widget needs.
Flexible(
child: Text('Long Text', maxLines: 3,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.justify,
),
),
Best way to handle this:
Expanded(
child: Text(document['content'],
textAlign: TextAlign.start,
overflow: TextOverflow.ellipsis,
maxLines: 20,
))
You can use this trick.
Text( ''' This is very big text''' ),
Just wrap a text around three single quotes and flutter will format a text as per its length . No need to use max lines and text field.
Maybe try using TextField:
new TextField(
keyboardType: TextInputType.multiline,
maxLines: 2,
)
wrap your Text widget with AutoSizeText widget and also Flexible widget.
AutoSizeText adjust your text size as per the screen size
Flexible control your widget not to overflow outside
for get AutoSizeText you have to add dependency.
auto_size_text: ^3.0.0 - Example
Maxline is used for set how many lines you want to set or see.
Text(
"Name Safal Bhatia",
style: TextStyle(fontSize: 16),
maxLines: 3,)
I have a tab bar functionality in which I show a Donut chart and list of vehicles but I need to show which tab the user selected for that I have indicatorColor in TabBar but I need to fill with gradient line as shown in the image please help me out.
PS: If possible please let me know how to give theme color means primary color in main as a gradient???
return Scaffold(
body: new DefaultTabController(
length: 2,
child: new Column(
children: <Widget>[
new Container(
width: 1200.0,
child: new Container(
color: Colors.white,
child: new TabBar(
labelColor: Colors.black,
tabs: [
Tab(
child: new Text("Visual",
style: new TextStyle(fontSize: 20.0)
),
),
Tab(
child: new Text("Tabular",
style: new TextStyle(fontSize: 20.0)),
),
],
),
),
),
new Expanded(
child: new TabBarView(
children: [
Tab(
child: new RefreshIndicator(
child: new Text('DONUT CHART'),
onRefresh: refreshList,
key: refreshKey1,
),
),
Tab(
child: new RefreshIndicator(
child: new Text('List of vehicles'),
onRefresh: refreshList,
key: refreshKey2,
),
),
],
),
),
],
),
),
);
Instead of changing core files here is a better answer that worked for me.
TabBar(
controller: tabController,
indicatorPadding: EdgeInsets.all(0.0),
indicatorWeight: 4.0,
labelPadding: EdgeInsets.only(left: 0.0, right: 0.0),
indicator: ShapeDecoration(
shape: UnderlineInputBorder(
borderSide: BorderSide(
color: Colors.transparent,
width: 4.0,
style: BorderStyle.solid)),
gradient: LinearGradient(colors: [pinkLight, pinkDark])),
tabs: <Widget>[
Center(
child: Container(
alignment: Alignment.center,
color: whiteColor,
child: Text(
"Rating",
style: themeData.accentTextTheme.title,
),
),
),
Container(
alignment: Alignment.center,
color: whiteColor,
child: Text(
"Category",
style: themeData.accentTextTheme.title,
),
),
Container(
alignment: Alignment.center,
color: whiteColor,
child: Text(
"Friend",
style: themeData.accentTextTheme.title,
),
),
],
),
make indicator padding to zero, label padding to zero and indicatorWeight to 4.0 or your require size after that instead of using text in tabs use Container at top and give it color.
I think the only way is to create your custom TabBar.
You can copy the code of TabBar from tabs.dart and in _TabBarState you have to change Decoration get _indicator.
Something like:
return ShapeDecoration(shape: UnderlineInputBorder(), gradient: LinearGradient(
colors: [Colors.blue, Colors.green]));
UPD:
Got it. ShapeDecoration doesn't work. With it I can set gradient for whole tab. For underline - there is _IndicatorPainter class in same file. And there is Rect indicatorRect method of this class.
return Rect.fromLTWH(tabLeft, 0.0, tabRight - tabLeft, tabBarSize.height);
This string return rect for decoration. If you change it - you can get underline:
return Rect.fromLTWH(tabLeft, tabBarSize.height - 4.0, tabRight - tabLeft, 4.0);
And inside Decoration get _indicator don't forget change return UnderlineTabIndicator to
return ShapeDecoration(shape: RoundedRectangleBorder(), gradient: LinearGradient(
colors: [Colors.blue, Colors.green]));
And here's result