I have this box decoration used for showing the reviews but I don't know what I should use to align the text properly. This is how it looks right now:
I want the username ("La fottaria to have some space left) I used Align( Alignment(8,3)) but it doesn't change the position.
return ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
return Container(
width: 200,
margin: EdgeInsets.only(
top: 8, bottom: 8, right: 12),
decoration: BoxDecoration(boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 2,
spreadRadius: 1)
], borderRadius: BorderRadius.circular(4)),
child: Column(
children: [
Row(
children: [
CircleAvatar(
backgroundImage: NetworkImage(
snapshot.data.documents[index]
.data["avatarUrl"]),
),
Align(
alignment: Alignment(8, 3),
child: Text(snapshot
.data
.documents[index]
.data["name"]),
)
],
),
_buildRatingStars(snapshot.data
.documents[index].data["rating"]),
Text(snapshot
.data.documents[index].data["text"])
],
),
);
}
);
Inside the Row widget, you can use a SizedBox with width property.
It will give some space.
Row(
children: [
CircleAvatar(
backgroundImage:
NetworkImage(snapshot.data.documents[index].data["avatarUrl"]),
),
//insert here
SizedBox(
width: 20.0,
),
Align(
alignment: Alignment(8, 3),
child: Text(snapshot.data.documents[index].data["name"]),
)
],
)
You can remove the Align widget if you want.
Instead of align widget, I suggest you to use Container widget like this:
Container(
margin: const EdgeInsets.only(left: 15),
child: Text(snapshot
.data
.documents[index]
.data["name"]),
)
Use Align
Example:
DecoratedBox(
decoration: BoxDecoration(
border: Border.all(
color: Colors.blue,
width: 1,
),
borderRadius: BorderRadius.circular(4),
),
child: Align(
alignment: Alignment.center, // align type
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 15),
child: Text(
title,
style: TextStyle(fontSize: 17, color: Colors.blue),
),
),
),
)
You can use some inbuilt property of rows i.e Main Axis Alignment and Cross Axis Alignment to align its children.For eg:
Row(
mainAxisAligment:MainAxisAlignment.spaceEvenly,
crossAxisAligment:CrossAxisAligment.center,
children: [
CircleAvatar(
backgroundImage:
NetworkImage(snapshot.data.documents[index].data["avatarUrl"]),
),
SizedBox(
width: 20.0,
),
Text(snapshot.data.documents[index].data["name"]),
],
)
You can wrap the text widget inside padding widget also to align according to your needs.
Related
I'm trying to expand and collapse a container dynamically based on the data received. Currently I'm doing it like this:
AnimatedContainer(
duration: const Duration(milliseconds: 550),
margin: EdgeInsets.symmetric(horizontal: 16),
constraints: !isExpanded
? BoxConstraints(
maxHeight: MyUtils.height(221),
minHeight: MyUtils.height(221))
: BoxConstraints(
minHeight: MyUtils.height(321),
maxHeight: MyUtils.height(1000)),
decoration: BoxDecoration(
color: containerColor,
borderRadius: const BorderRadius.all(Radius.circular(8))),
child: Column(children: [
Container(
margin: EdgeInsets.fromLTRB(8, 10, 8, 20),
height: MyUtils.height(36),
width: double.infinity,
decoration: BoxDecoration(
color: containerColor3,
borderRadius: BorderRadius.all(Radius.circular(6))),
),
InkWell(
onTap: () => expand(),
child: Text(
'Show',
style: TextStyle(color: Colors.white),
),
)
]),
),
The function expand() is as simple as changing the bool of isExpanded. I managed to collapse/expand the Container, but the problem is that the Container expanded until maxHeight, I want to make the expanded height dynamic based on the items inside. So I tried to set only minHeight and hoping that maxHeight will follow the items, but I got an error because maxHeight is not set.
Is there any way I can achieve this?
By default, Column tries to be as much as possible. You can control this behavior by specifying mainAxisSize param.
Column(
mainAxisSize: MainAxisSize.min, // ADD THIS LINE TO YOUR COLUMN
children: [...]
)
I recommend that you read this article https://docs.flutter.dev/development/ui/layout/constraints
Try to Do this Hope this will be helpful:
Table(children: [
TableRow(children: [
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
alignment: Alignment.center,
child: Text('Widget'),
),
Container(
alignment: Alignment.center,
child: Text('Widget'),
),
],
),
]),
]),
AlignedGridView.count(
crossAxisCount: 4,
mainAxisSpacing: 4,
crossAxisSpacing: 4,
itemBuilder: (context, index) {
return Tile(
index: index,
extent: (index % 7 + 1) * 30,
);
},
);
use this package flutter_staggered_grid_view
I wanted to get same dynamic height of right widget to left widget in Row Widget.Below I was attaching screenshot of my expected design. Could you help how can do that.
We can see right side date widget is expanding , So I wanted to get the height of left side widget(blue and purple) same as right side widget.
If left side image widget is not possible to expand the height then is any there any possible to create custom widget, Any solution is welcome.
Thanks in advance.
Row(
children: [
Align(
alignment: Alignment.topCenter,
child: Container(
constraints: BoxConstraints(
minHeight: 40.0,
maxHeight: 50.0,
/*maxWidth: 10,
minWidth: 10,*/
),
padding: EdgeInsets.only(top: 0.0),
//height: 98,
width: 20,
child: ShaderMask(
shaderCallback: (bounds) {
return LinearGradient(
colors: [Color(0xff12229F), Color(0xff615FDF)],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
).createShader(bounds);
},
child: ImageIcon(
AssetImage('assets/images/reservations/small_timeline.png'),
color: Colors.white,
size: 40,
),
),
),
),
Expanded(
child: Column(
children: [
pickup(data),
dropoff(data),
],
),
),
],
),
After Using IntrinsicHeight
I was unable to remove default padding around the icons
IntrinsicHeight(
child: Padding(
padding: const EdgeInsets.only(top: 0,bottom: 0),
child: Row(
children: [
Column(
children: [
Padding(
padding: const EdgeInsets.only(top: 4),
child: Icon(
Icons.fiber_manual_record,
size: 18,
color: Color(0xff11219E),),
),
Flexible(
child: Container(
decoration: BoxDecoration(
gradient:
LinearGradient(colors: [Color(0xff11219E), Color(0xff6F6AEB)]),
),
width: 4,
),
),
Padding(
padding: const EdgeInsets.only(bottom: 4),
child: Icon(
Icons.fiber_manual_record,
size: 18,
color: Color(0xff6F6AEB),),
),
],
),
Expanded(
child: Column(
children: [
pickup(data),
dropoff(data),
],
),
),
],
),
),
),
It seems to me that Expanded could be used to expand your widget to full availabe height.
Keep in mind that the Row width will distribution will also expand, since no flex parameter is provided.
You already have an Expanded on the right widget so just add the other one and provide a flex value for both of them.
Some thing like 10 for left and 90 for right should work for you :)
I'm trying to make this drawing but I'm struggling.
I don't understand how to make the white block of information dynamic. That is to say that it automatically adapts to the size in height of the elements it contains.
I am for the moment obliged to give a defined height (here 200), I would like the size to be automatic. Moreover if I do not give a defined size my gray line on the left side disappears.
The design :
ListTile(
title : Column(
children: [
Container(
width: double.infinity,
child: Row(
children: [
Container(
width: 50,
alignment: Alignment.center,
child: Container(
width: 20,
height: 20,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(40),
border: Border.all(
width: 5,
color: Colors.blue,
style: BorderStyle.solid
)
),
),
),
Text('9:00 am - 9:15 am')
],
)
),
Container(
child: IntrinsicHeight(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
width : 50,
alignment: Alignment.center,
child: IntrinsicHeight(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
color: Colors.grey,
width: 3,
height : 200 // if I remove the size it desappear
),
],
),
),
),
Expanded(
child: Container(
margin: EdgeInsets.symmetric(vertical :10),
padding: EdgeInsets.symmetric(vertical: 20, horizontal: 10),
color: Colors.white,
child: Column(
children: [
Text('Titre'),
Text('Info 1'),
Text('Info 2')
],
),
),
)
],
),
),
)
],
),
),
You can try this package for timelines https://pub.dev/packages/timeline_tile.
This package also automatically Sizes your widget height and width.
And for Automatically Sizing your widgets next time, You could use Expanded widget at most places in your code.
Note: An Expanded widget must be a descendant of a Row, Column, or Flex, So Use it carefully.
I think it's much easier with this package, timelines.
TimelineTileBuilder.connected(
connectionDirection: ConnectionDirection.before,
itemCount: processes.length,
contentsBuilder: (_, index) {
//your Container/Card Content
},
indicatorBuilder: (_, index) {
if (processes[index].isCompleted) {
return DotIndicator(
color: Color(0xff66c97f),
child: Icon(
Icons.check,
color: Colors.white,
size: 12.0,
),
);
} else {
return OutlinedDotIndicator(
borderWidth: 2.5,
);
}
},
connectorBuilder: (_, index, ___) => SolidLineConnector(
color: processes[index].isCompleted ? Color(0xff66c97f) : null,
),
),
),
I am trying to create a gridview starting from the second column. The first card is just a static card with a button in it. So the second card starting should be dynamic.
All the cards have the same width and height. So basically they all should look like the first card (Add a new dog)
But it's not filling out the space as I expected it would.
Here is part of my code from the body section:
body: Stack(fit: StackFit.expand, children: [
//bg image
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(Images.bgYellow), fit: BoxFit.cover)),
),
//content
SafeArea(
bottom: false,
left: true,
right: true,
top: false,
child: Padding(
padding: EdgeInsets.all(3 * SizeConfig.safeBlockHorizontal),
child: GridView.count(
crossAxisCount: 2,
children: [
//add card
Container(
margin: EdgeInsets.symmetric(
vertical: 1 * SizeConfig.blockSizeVertical,
horizontal: 2 * SizeConfig.blockSizeHorizontal),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
spreadRadius: 2,
blurRadius: 8,
offset: Offset(
0, 2), // changes position of shadow
),
],
),
child: FlatButton(
onPressed: null,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
const IconData(0xe901,
fontFamily: 'icDog'),
color: muddyBrown,
size: 20 * SizeConfig.safeBlockHorizontal,
),
SizedBox(height: 5),
Text(
"ADD A NEW DOG",
style: TextStyle(
color: muddyBrown,
fontWeight: FontWeight.bold,
fontSize: 4 *
SizeConfig.safeBlockHorizontal),
)
],
)),
),
//dynamic content
StateBuilder<PetState>(
observe: () => _petStateRM,
builder: (context, model) {
return Column(
children: [
...model.state.pets.map((pet) =>
GestureDetector(
onTap: () {
Navigator.pushNamed(
context, petDetailRoute);
},
child: Container(
margin: EdgeInsets.symmetric(
vertical: 1 *
SizeConfig
.blockSizeVertical,
horizontal: 2 *
SizeConfig
.blockSizeHorizontal),
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(30),
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey
.withOpacity(0.5),
spreadRadius: 2,
blurRadius: 8,
offset: Offset(0,
2), // changes position of shadow
),
],
),
child: Column(
mainAxisAlignment:
MainAxisAlignment.center,
//dynamic data => Photo + Name
children: [
Container(
width: 100.0,
height: 100.0,
decoration: new BoxDecoration(
color:
const Color(0xff7c94b6),
image: new DecorationImage(
image: new NetworkImage(
"${pet.photo}"),
fit: BoxFit.cover,
),
borderRadius:
new BorderRadius.all(
new Radius.circular(
50.0)),
border: new Border.all(
color: muddyBrown,
width: 4.0,
),
),
),
SizedBox(height: 5),
Text(
"${pet.name}",
style: TextStyle(
fontSize: 4 *
SizeConfig
.safeBlockHorizontal,
color: muddyBrown,
fontWeight:
FontWeight.bold),
)
],
),
),
))
],
);
}),
],
)
)),
]));
What about simply adding the 'static' card to the 'dynamic' ones and then build one GridView with all of them together?
Widget newDogButton = Card(...);
//dynamic content
StateBuilder<PetState>(
observe: () => _petStateRM,
builder: (context, model) {
return Column(
children: [
newDogButton,
...model.state.pets.map((pet) => // ...
That should take care of most of your layout issues automatically.
Because StateBuilder return a widget. How about moving the Whole GridView inside it?
...
child: Padding(
padding: EdgeInsets.all(3 * SizeConfig.safeBlockHorizontal),
child: StateBuilder<PetState>(
observe: () => _petStateRM,
builder: (context, model) {
return GridView.count(
crossAxisCount: 2,
children: [
// The button "ADD A NEW DOG" here,
Container(...),
//dynamic content here
...model.state.pets.map((pet) =>
...
).toList(),
},
),
),
Every grid item in GridView will have same height and width, if you want different dynamic height or width for different items, use flutter_staggered_grid_view, in your case:
StaggeredGridView.countBuilder(
crossAxisCount: 2,
itemCount: 2,
itemBuilder: (BuildContext context, int index) => new Container(
color: Colors.green,
child: new Center(
child: new CircleAvatar(
backgroundColor: Colors.white,
child: new Text('$index'),
),
)),
staggeredTileBuilder: (int index) =>
new StaggeredTile.count(1, index.isEven ? 2 : 1),
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
)
The situation:
To me, this problem is not coming from your Dynamic content but from the height allowed to it to display it's content. Inside the GridView.count constructor, the default childAspectRatio value is 1.0, meaning that the default max height of each child of the GridView is deviceWidth / crossAxisCount (2 in your case).
The problem:
In order for each child to display correctly, it's height must not exceed this ratio (causing your overflowed error).
My opinion:
To solve this problem, I will either replace the dynamic content StateBuilder<PetState> with a static Widget which height will not exceed the ratio OR wrap the dynamic content StateBuilder<PetState> in a SingleChildScrollView to ensure that the overflowed error will not happen and the wrapper can produce the scroll effect to see the entire dynamic content.
I have the following code where I'm trying to make a column inside which is a container containing title, and another container containing a list of items, that is scrollable horizontally. But I get the following runtime error - "
The following assertion was thrown during performResize():
Horizontal viewport was given unbounded height.
Viewports expand in the cross axis to fill their container and constrain their children to match their extent in the cross axis. In this case, a horizontal viewport was given an unlimited amount of vertical space in which to expand."
Widget horizontalSlider(MediaQueryData mediaQuery){
final List<String> entries = <String>['A', 'B', 'C','D','E'];
return Container(
padding: EdgeInsets.all(0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: EdgeInsets.only(left:16),
child: Text("Home",style: TextStyle(fontSize: 36, fontWeight: FontWeight.bold),)
),
Container(
child: ListView.builder(
padding: EdgeInsets.all(8),
itemCount: entries.length,
itemBuilder: (BuildContext context, int index){
return Column(
children: <Widget>[
Container(
height: mediaQuery.size.height/3,
margin: EdgeInsets.all(8),
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/$index.jpg'),
fit: BoxFit.cover,
),
borderRadius: BorderRadius.circular(18),
boxShadow: [BoxShadow(
color: Colors.grey.withOpacity(0.5),
spreadRadius: 4,
blurRadius: 4,
),],
),
width: mediaQuery.size.width/1.5,
),
Text("Item ${entries[index]}",style: TextStyle(fontSize: 18),),
],
);
},
scrollDirection: Axis.horizontal,
),
)],
),
);
}
What I expect from this is a heading (i.e. the first container inside the first column), an image of height equal to one-third of screen height and a Text widget at the end. But why do I get the error I cannot understand.
Finally I found the answer from this thread https://github.com/flutter/flutter/issues/18341. I have to replace the second Container with Expanded and it works well. Updated Code
Widget horizontalSlider(MediaQueryData mediaQuery){
final List<String> entries = <String>['A', 'B', 'C','D','E'];
return Container(
padding: EdgeInsets.all(0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: EdgeInsets.only(left:16),
child: Text("Home",style: TextStyle(fontSize: 36, fontWeight: FontWeight.bold),)
),
Expanded(
child: ListView.builder(
padding: EdgeInsets.all(8),
itemCount: entries.length,
itemBuilder: (BuildContext context, int index){
return Column(
children: <Widget>[
Container(
height: mediaQuery.size.height/3.5,
margin: EdgeInsets.all(8),
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/$index.jpg'),
fit: BoxFit.cover,
),
borderRadius: BorderRadius.circular(18),
boxShadow: [BoxShadow(
color: Colors.grey.withOpacity(0.5),
spreadRadius: 4,
blurRadius: 4,
),],
),
width: mediaQuery.size.width/1.5,
),
Text("Item ${entries[index]}",style: TextStyle(fontSize: 18),),
],
);
},
scrollDirection: Axis.horizontal,
),
)],
),
);
}