Flutter : Different width container depend of value - flutter

I want to implement a design like the one above, the problem is i don't know how to make the container size different depending on the number.
Expectaion
Source code
final userPlaylist = {
'Kaguya Love Dramatic': 10,
'Saenai Heroine': 8,
'Jujutsu Kaisen Kaikai Kitan': 3,
'Jujutsu Kaisen LOST IN PARADISE': 2,
'Kaguya Sama DADDY DADDY DO': 2,
};
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: userPlaylist.length,
itemBuilder: (context, index) {
final song = userPlaylist.keys.elementAt(index);
final totalPlay = userPlaylist.values.elementAt(index);
final margin = margins[index];
return Padding(
padding: const EdgeInsets.only(top: 12),
child: Row(
children: [
Expanded(child: CircleAvatar()),
SizedBox(width: 10),
Expanded(
flex: 4,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(song),
SizedBox(height: 10),
Container(
margin:EdgeInsets.only(right:margin),
height: 20,
decoration: BoxDecoration(
color: Colors.green,
),
),
],
),
),
SizedBox(width: 10),
Expanded(child: Text(totalPlay.toString(),style: TextStyle(color:Colors.white),))
],
),
);
},
),
],
);
}
}
and this size container applies if there are numbers that have the same value

Add a variable max right after the margin definition. This reduces the list of values to the largest value in the list:
final max = userPlaylist.values.reduce((curr, next) => curr > next ? curr : next);
Replace the green Container with:
Row(
children: [
Expanded(
flex: totalPlay,
child: Container(
height: 20,
decoration: BoxDecoration(
color: Colors.green,
),
),
),
Expanded(
flex: max - totalPlay,
child: Container(),
)
],
)
The green bar is a Row widget containing two Expanded widgets. The first Expanded widget has flex: totalPlay, and the second flex: max - totalPlay. This would show a green bar, the length is the song's value proportional to the max value.
(margin is not used)

Make each bar like this:
Row(
children: [
Expanded(
flex: totalPlay,
child: Container(color: Colors.green),
),
Expanded(
flex: maxTotalPlay - totalPlay,
child: Container(),
),
],
),
flexes of two Expanded widgets should divide the parent width proportionally among them.

Related

how can i set the size of the child inside the row?

I want to make children use flexible sizes
how can i set the size of the child inside the row? can you guys help me? and find the error constraint
anyone help me
return SafeArea(
child: Column(
children: [
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: [
Container(
color: Colors.lightBlue,
child: Row(
children: [
Expanded(
flex: 5,
child: Container(
color: Colors.green,
),
),
Expanded(
flex: 5,
child: Container(
color: Colors.blue,
),
)
],
),
)
],
),
)
],
),
);
To place children in a row you can use Flexible widget. The value of flex defines how much space each child should take. In the example that you provided.. Both children will be equally spaced since you gave flex value 5 for both.
return Scaffold(
body: Center(
child: SizedBox(
height: 50,
child: Row(
children: [
Flexible(
flex: 5,
child: Container(
color: Colors.red,
)),
Flexible(
flex: 5,
child: Container(
color: Colors.green,
)),
],
),
),
),
);
If you change the flex value to 1 and 5.. Now the total divisions will be 6 and out of that the first child will take 1 part and the second child will take 5 parts like below
return Scaffold(
body: Center(
child: SizedBox(
height: 50,
child: Row(
children: [
Flexible(
flex: 1,
child: Container(
color: Colors.red,
)),
Flexible(
flex: 5,
child: Container(
color: Colors.green,
)),
],
),
),
),
);
Also if you use a singleChildScrollView and an expanded inside that it then the expanded widget has no bounds so it will throw an error. So wrapping the Expanded with a SizedBox with a specific width will give you expected results.
EDIT
To have a SingleChildScrollView with dynamic content in the row you can do this
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisSize : MainAxisSize.min,
children:[
SizedBox(
width: 100,//this is important since its a row and the row will take full width and throw an error.
child: Image.asset(""),
),
//Another SizedBox or Text or any widget..
]
)
)

Expanding a widget horizontally inside column

I'm facing some problem by composing layout of my App.
My widget at the end sould look like this
This is my code
Row(
mainAxisSize: MainAxisSize.max,
children: [
Column(
children: [
// Widget A
SizedBox(
height: widget.screenHeight * 0.9,
child: AspectRatio(
aspectRatio: 16 / 9,
child: Container(
color: Colors.red,
),
),
),
// Widget B
Container(
height: widget.screenHeight * 0.1,
color: Colors.green,
)
],
),
// Widget C
Expanded(
child: Container(
color: Colors.pink,
),
)
],
)
I want Widget A to occupy 90% of screen height and mantain a 16/9 aspect ratio, Widget B to occupy remaining 10% height and have the same width of his sibling, and Widget C to fill remaining space
With that code, Widget A and Widget C are showed correctly, but widget B doesn't fill his space as i expect.
What's wrong?
Column(
children: [
Expanded(
child: Row(
children: [
Expanded(
flex: 2,
child: Column(
children: [
Expanded(
flex:4,
child: Container(
color: Colors.yellow,
),
),
Expanded(
flex: 1,
child: Container(
color: Colors.blue,
),
)
],
),
),
Expanded(
flex: 1,
child: Container(
color: Colors.green,
),
),
],
),
)
],
),
you have to play with the expanded widget

Flutter Alignment Containers

So I'm working on my first Project. Basically I want to alignment 4 containers equally. they should have same size H/W so i could scroll on them whenever extra data has been put into them later.....
Here's my Code
Widget build(BuildContext context) {
return Center(
child: Scaffold(
body: Center(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
children: [
Row(
children: [
VerticalText1(),
DoBuilder(),
],
),
Column(
children: const [
SizedBox(
width: 10,
)
],
),
Column(
children: [
DecideBuilder(),
],
),
],
),
Row(
children: const [
SizedBox(
height: 10,
)
],
),
Row(
children: [
Row(
children: [
VerticalText2(),
DelegateBuilder(),
],
),
Column(
children: const [
SizedBox(
width: 10,
)
],
),
Align(
alignment: Alignment.bottomLeft,
child: DeleteBuilder(),
),
So I'm working on my first Project. Basically I want to alignment 4 containers equally. they should have same size H/W so i could scroll on them whenever extra data has been put into them later.....So I'm working on my first Project. Basically I want to alignment 4 containers equally. they should have same size H/W so i could scroll on them whenever extra data has been put into them later.....
for me I'm also a beginner in flutter but I know something that if you want actual size for container and you want it to be some kind of responsive you have 2 ways to do that:
first you can use:
(Mediaquery).of(context).size.width or
(media.query).of(context).size.height
that will give you the size of your screen and you can use as much as you need from it for each container for example:
Container(
child:,
width: (MediaQuery.of(context).size.width / 2))
that will give you half of your screen width what ever the device run the app the size will be the same for the screen size
and other way you can use expanded widget:
put every container in expanded widget and give the flex parameter value of one
here is an example:
Row(children:[
Expanded(flex:1,child:Container()),
Expanded(flex:1,child:Container()),]),
expanded will sum the flexes and will divide the space of the screen on element all equal repeat the above code in single Column has 2 Rows and I hope your code will work as you want
Instead of row and column, you should try with the GridView otherwise you can try with media query height and width.
GridView.builder(
itemCount: 4,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
itemBuilder: (BuildContext context, int index) {
return new Card(
child: Container(
color: Colors.green,
child: Center(child: Text("$index"),),
),
);
},
)
And Using Column and row
idget build(BuildContext context) {
double height = MediaQuery.of(context).size.height;
double width = MediaQuery.of(context).size.width-20;
return Scaffold(
appBar: AppBar(
title: Text("widget.title"),
),
body: Stack(
children: [
Column(
children: [
Expanded(
child: Row(
children: [
Container(
height: height / 2,
width: width/2,
color: Colors.green,
),
SizedBox(width: 10,),
Container(
height: height / 2,
width: width / 2,
color: Colors.green,
)
],
),
),
SizedBox(height: 10,),
Expanded(
child: Row(
children: [
Container(
height: height / 2,
width: width / 2,
color: Colors.green,
),
SizedBox(width: 10,),
Container(
height: height / 2,
width: width / 2,
color: Colors.green,
)
],
),
),
],
),
Center(
child: Padding(
padding: const EdgeInsets.only(right:10.0),
child: CircleAvatar(child: Icon(Icons.home),),
),
)
],
),
);
}
Output:

Is there a way to get fixed size for child inside GridView?

Is there a way to have a fixed size for the child inside GridView? I wanted to have the red color be same height. I tried using Expanded or specified the size for the Container, but it just won't work. GridView just makes the child same size.
Note: I tried specify the height for the red Container. It didn't work.
This is what I got.
This is what I did.
return GridView.count(
crossAxisCount: 2,
children: List.generate(drinksData.length, (index) {
return Container(
padding: EdgeInsets.all(20.0),
child: Column(
children: [
Expanded(
child: Container(
color: Colors.red,
),
),
Text(drinksData[index].label),
],
),
);
}),
);
GridView.count(
crossAxisCount: 2,
children: List.generate(drinksData.length, (index) {
return Container(
padding: const EdgeInsets.all(20.0),
child: Column(
children: [
Expanded(
child: Container(
// height:90,//or whatever size you want!
color: Colors.red,
),
),
SizedBox(
height: 45,
child: Text(drinksData[index])
),
],
),
);
}),
)
```

Row with a vertical picture and a horizontal picture with minimum white space?

I am trying to lay out a List of images containing a mix of portrait and landscape images and I would like to minimize white space. For now, I have a column whose children are rows whose children are Flexible whose child are Images:
class MyHomePage extends StatelessWidget {
MyHomePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Row(
children: [
Flexible(
child: Image.network(
'https://via.placeholder.com/400x600',
),
),
SizedBox(
width: 8,
),
Flexible(
child: Image.network(
'https://via.placeholder.com/400x600',
),
),
],
),
SizedBox(
height: 8,
),
Row(
children: [
Flexible(
child: Image.network(
'https://via.placeholder.com/600x400',
),
),
SizedBox(
width: 8,
),
Flexible(
child: Image.network(
'https://via.placeholder.com/600x400',
),
),
],
),
SizedBox(
height: 8,
),
Row(
children: [
Flexible(
child: Image.network(
'https://via.placeholder.com/400x600',
),
),
SizedBox(
width: 8,
),
Flexible(
child: Image.network(
'https://via.placeholder.com/600x400',
),
),
],
),
SizedBox(
height: 8,
),
Row(
children: [
Flexible(
child: Image.network(
'https://via.placeholder.com/600x400',
),
),
SizedBox(
width: 8,
),
Flexible(
child: Image.network(
'https://via.placeholder.com/400x600',
),
),
],
),
],
),
),
),
),
);
}
}
This example project demonstrates all the scenarios I want my layout to handle.
So in an app, I get the following:
So as you can see, when a row contains a portrait and a landscape image, the shortest image has a lot of space above and below. And I would like to lay out my images so that the cells of the row are not the same width, but their widths adapt so that the shortest image gets taller and the tallest image gets shorter and they both occupy the full height of the row, without messing with their respective aspect ratios of course.
How can I do that?
By the way, I put together a sample project with the simplest version of my problem here.
have you considered using this package?
Update
if you don't want to use a package, you might try something like this:
final List<Widget> _images = [
Image.network('https://via.placeholder.com/400x600'),
Image.network('https://via.placeholder.com/400x600'),
Image.network('https://via.placeholder.com/600x400'),
Image.network('https://via.placeholder.com/600x400'),
Image.network('https://via.placeholder.com/400x600'),
Image.network('https://via.placeholder.com/600x400'),
Image.network('https://via.placeholder.com/600x400'),
Image.network('https://via.placeholder.com/400x600'),
];
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
child: Wrap(
runSpacing: 8,
children: images
.where((element) => images.indexOf(element) % 2 == 0)
.toList(),
),
),
SizedBox(width: 8),
Expanded(
child: Wrap(
runSpacing: 8,
children: images
.where((element) => images.indexOf(element) % 2 == 1)
.toList(),
),
),
],
),
),
),
),
);
}
or using list of urls:
class MyHomePage extends StatelessWidget {
final List<String> _images = [
'https://via.placeholder.com/400x600',
'https://via.placeholder.com/400x600',
'https://via.placeholder.com/600x400',
'https://via.placeholder.com/600x400',
'https://via.placeholder.com/400x600',
'https://via.placeholder.com/600x400',
'https://via.placeholder.com/600x400',
'https://via.placeholder.com/400x600',
];
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
child: Wrap(
runSpacing: 8,
children: [
for (int index = 0; index < _images.length; index += 2)
Image.network(_images[index])
],
),
),
SizedBox(width: 8),
Expanded(
child: Wrap(
runSpacing: 8,
children: [
for (int index = 1; index < _images.length; index += 2)
Image.network(_images[index])
],
),
),
],
),
),
),
),
);
}
}
If you dont want to use the staggered_grid I create the same goal with 2 Columns, left for odd index and right for even index