How to put elements under each other with a ListView? - flutter

I'm having a hard time to put items under each other when a ListView is involved.
I've this code :
body:
Column(
children: [
Text('foo'),
Expanded(
child: ListView.builder(
controller: ...,
itemCount: ...,
itemBuilder: ...
)
),
Text('bar')
]
)
,
It gives me the result on the left, but I'd like the one on the right :
I tried to put the ListView in a Container (with an height: double.maxFinite) but its give me an : Bottom overflowed by X pixels.
Edit : Here is the result I'm trying to achieve (run the snippet in "full page") :
body {
font-size: 18px;
margin: 0;
padding: 0;
}
.mobile {
position: relative;
width: 320px;
margin: 0 auto;
border: 1px solid cyan;
max-height: 400px;
overflow-y: scroll;
padding-top: 41px;
}
.appbar {
position: fixed;
top: 0;
width: 300px;
background: rgba(0, 0, 0, 1);
color: white;
padding: 10px;
}
.text {
background: rgba(255, 0, 0, .3);
padding: 10px;
}
.list-view {
background: rgba(0, 255, 0, .3);
padding: 10px;
min-height: 500px;
}
<div class="mobile">
<div class="appbar">AppBar</div>
<div class="text">Text</div>
<div class="list-view">ListView</div>
<div class="text">Text</div>
</div>

You have to use a CustomScrollView
CustomScrollView(
slivers: <Widget>[
SliverToBoxAdapter(
child: Text("Text"),
),
SliverList(
delegate: SliverChildListDelegate( [
Container(
height: 200.0,
decoration: BoxDecoration(color: Colors.orange),
),
Container(
height: 400.0,
decoration: BoxDecoration(color: Colors.pink),
),
Container(
height: 500.0,
decoration: BoxDecoration(color: Colors.blue),
)
]),
),
SliverToBoxAdapter(
child: Text("Text"),
),
],
)
Notice you can use a SliverChildListDelegate or a SliverChildBuilderDelegate

Try this one
body:
Column(
children: [
Text('foo'),
Expanded(
child: Container(
child: ListView.builder(
shrinkWrap: true,
itemBuilder: .......,
itemCount: .....,
),
),
),
Text('bar')
]
)
,
This code worked for me.

You can add the top and bottom foo and bar as the first and last items of the list. The ListView will have list.length + 2 items.
body: Column(children: [
Text('foo'),
Expanded(
child: ListView.builder(
itemCount: list.length + 2,
itemBuilder: (context, index) {
if (index == 0)
return Text("foo");
else if (index < list.length + 1)
return Text("$index");
else
return Text('bar');
},
),
),
]),

Related

how to make widget scale up when it selected in Flutter

I have an app that has pageView.builder and it contains 5 stack widget
how can I scale up the widget that user-selected, for example:
if the user scrolls to widget 3, widgets 1 & 2 become smaller than widget 3, and the same if he scrolls to widget 5 or 2
( the middle will become bigger than the widget on both sides)
my code :
Widget build(BuildContext context) {
// ignore: sized_box_for_whitespace
return Container(
height: 320,
child: PageView.builder(
controller: pageController,
itemCount: 5,
itemBuilder: (context, position) {
return _bulidPageItem(position);
}),
);
}
Widget _bulidPageItem(int index) {
//------------------------------------------------------------------------------
// Slide image 🚩
return Stack(
alignment: Alignment.topCenter,
children: [
Container(
margin: const EdgeInsets.only(left: 5, right: 5),
height: 220,
width: 350,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: index.isEven
? const Color(0xFFffd28d)
: const Color(0xFF89dad0),
image: const DecorationImage(
image: AssetImage('images/chineseFood.jpg'), fit: BoxFit.cover),
),
),
//------------------------------------------------------------------------------
// Slide Information 🚩
Align(
alignment: Alignment.bottomCenter,
child: Container(
margin: const EdgeInsets.only(left: 30, right: 30, bottom: 15),
height: 130,
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.3),
blurRadius: 6,
spreadRadius: 0.7,
offset: const Offset(1, 4))
],
borderRadius: BorderRadius.circular(25),
color: Colors.white,
),
//------------------------------------------------
// Slider title
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const BigText(
text: 'Chinese side',
),
//----------------------------------------------
// Slider Rating
const SizedBox(height: 10),
Row(
children: [
Wrap(
children: List.generate(
5,
(index) => const Icon(Icons.star,
color: AppColor.mainColor, size: 12),
),
),
const SizedBox(width: 10),
SmallText(text: 4.5.toString()),
const SizedBox(width: 10),
const SmallText(text: '1287 comments'),
],
),
const SizedBox(height: 20),
//----------------------------------------------
// Slider Icons
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: const [
SliderIcons(
color: AppColor.iconColor1,
text: 'Normal',
icon: Icons.circle),
SliderIcons(
color: AppColor.mainColor,
text: '1.7km',
icon: Icons.location_pin),
SliderIcons(
color: AppColor.iconColor2,
text: '32min',
icon: FontAwesomeIcons.clock),
],
),
],
),
),
),
),
],
);
}
}
I think the carousel slider package provides the functionality you need. The package has an example, which exactly describes your issue.
you should try out https://api.flutter.dev/flutter/widgets/ListWheelScrollView-class.html
and for your layout, you can use rotate widget for the horizontal view and of course
you to use rotate widget on the child of the list too.
Save the current page and adjust the content based on that. Like below the current page, _currentPage == index, has smaller margins.
final _pageController = PageController(viewportFraction: 0.8);
int _currentPage = 0;
...
PageView.builder(
controller: _pageController,
itemCount: 5,
itemBuilder: (_, index) =>
Container(
margin: _currentPage == index
? const EdgeInsets.symmetric(vertical: 16)
: const EdgeInsets.symmetric(vertical: 64),
child: Image.network(
'https://picsum.photos/1080/1920?index=$index',
fit: BoxFit.cover,
loadingBuilder: (_, child, loadingProgress) {
if (loadingProgress == null) return child;
return const Center(child: CircularProgressIndicator());
}
)
),
onPageChanged: (page){
setState(() {
_currentPage = page;
});
},
)
)

How to design horizontal scroll bar with separate colors

I have designed a horizontal scroll bar. here you can see my code. I want to design this bar according to the left side UI. The right side image shows my implementation so far. how do I design this with separate colours as the image shows?
final List<String> data = ["FRUIT AND BERRIES", "VEGETABLES", "BREAD","MILK"];
Padding(
padding: const EdgeInsets.only(top: 20, left: 20, right: 20),
child: Column(
children: [
SizedBox(
height: 50,
child: ListView.separated(
itemCount: data.length,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) =>
itemW(color: Color(0xffEEEACF), text: data[index]), //try to change text colour from here but it change whole box color. :(
separatorBuilder: (context, index) {
return const SizedBox(
width: 5,
);
},
),
),
],
),
),
//horizontal scroll bar
Widget itemW({
required String text,
required Color color,
}) {
return Container(
padding: const EdgeInsets.all(16),
alignment: Alignment.center,
decoration: ShapeDecoration(
shape: const StadiumBorder(),
color: color,
),
child: Text(text),
);
}
You can use a map to map items with colors.
final Map<String,Color> itemColors = {
"FRUIT AND BERRIES" : Color(0xffEEEACF),
"VEGETABLES": Color(0xffFFFFFF),
"BREAD" : Color(0xff000000),
"MILK" : Color(0xffFF0000)
}
full Code:
final List<String> data = ["FRUIT AND BERRIES", "VEGETABLES", "BREAD","MILK"];
final Map<String,Color> itemColors = {
"FRUIT AND BERRIES" : Color(0xffEEEACF),
"VEGETABLES": Color(0xffFFFFFF),
"BREAD" : Color(0xff000000),
"MILK" : Color(0xffFF0000)
}
Padding(
padding: const EdgeInsets.only(top: 20, left: 20, right: 20),
child: Column(
children: [
SizedBox(
height: 50,
child: ListView.separated(
itemCount: data.length,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) =>
itemW(color: itemColors[data[index]]!, text: data[index]), //try to change text colour from here but it change whole box color. :(
separatorBuilder: (context, index) {
return const SizedBox(
width: 5,
);
},
),
),
],
),
),
//horizontal scroll bar
Widget itemW({
required String text,
required Color color,
}) {
return Container(
padding: const EdgeInsets.all(16),
alignment: Alignment.center,
decoration: ShapeDecoration(
shape: const StadiumBorder(),
color: color,
),
child: Text(text),
);
}

spacing in horizontal listview.builder

How to do auto spacing in listview.builder().For example i need something like MainAxisAlignment.spaceEvenly in column, but i need it in list view.builder().I will have two or three not scrollable horizontal items.So i need spacing between items for different sceen sizes.Could you help me.
ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 3,//list.length expected two or three
itemBuilder: (BuildContext context, int index) {
return Container(
height: 100,
width: 100,
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(Radius.circular(10.0)),
color: Colors.amber,
border: Border.fromBorderSide(
BorderSide(
color: Color(0xFF8D4AE9),
width: 1.0,
),
),
),
);
},
),
For example, picture
enter image description here
add margin and padding as much you want.
ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 7,//list.length expected two or three
itemBuilder: (BuildContext context, int index) {
return Container(
height: 100,
width: 100,
margin: EdgeInsets.all(10),// add margin
padding: EdgeInsets.all(10),// add padding
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(Radius.circular(10.0)),
color: Colors.amber,
border: Border.fromBorderSide(
BorderSide(
color: Color(0xFF8D4AE9),
width: 1.0,
),
),
),
);
},
)
You can try adding a SizedBox with fixed height: or width: or even both between the content you want. Another solution is adding Padding with equal values.
First you have to wrap your list view with the container or card or sized box if you want the horizontal Scroll of the list. Next how you just wrap your return width with the padding to the padding to get the padding.
Try this code:
Container(
height: 100,width: MediaQuery.of(context).size.width,
child:
ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 13,
itemBuilder: (context, i) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: 100,
decoration: BoxDecoration(
color: Colors.black,
),
),
);
},
),
),

Want to display X amount of lines evenly separated on the screen

I'm trying to display a number of horizontal lines on the screen.
What would be the best approach to achieve this?
I attempted the following though the screen height returned seems to be bigger than the actual screen height so the divisions end up off the screen. I end up with the image shown at https://imgur.com/a/Dx1wH1Y.jpg
final int _numLines = widget._verticalLines;
return ListView.builder(
itemCount: _numLines,
itemBuilder: (BuildContext ctxt, int index) {
return Padding(
padding: EdgeInsets.only(
top: MediaQuery.of(context).size.height / (_numLines + 1),
),
child: Container(
height: 1.0,
width: MediaQuery.of(context).size.width,
color: Colors.red,
),
);
});
One way you can do this is like this.
Widget build(BuildContext context) {
final int _numLines = widget._verticalLines;
return Column(
children: getChildren(_numLines),
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
);
}
List<Widget> getChildren(int number) {
List<Widget> list = [];
for (int i = 0; i < number; i++) {
list.add(
Container(
height: 1.0,
width: MediaQuery.of(context).size.width,
color: Colors.red,
),
);
}
return list;
}
if i understand your question correctly,try this if it is not let me know
ListView.builder(
itemCount: 5,
shrinkWrap:true,
itemBuilder: (context, index) {
return Container(
height:120,
decoration: BoxDecoration(
border: Border(bottom: BorderSide(color: Colors.red,width: 2,)),
),
);
},
)
Use MediaQuery and divide the height of the screen by the given number
Example: MediaQuery.of(context).size.height / 5. - This will be dividing the screen into five equal parts, this will work across all devices.
Code:
ListView.builder(
shrinkWrap:true,
itemCount: number,
itemBuilder: (BuildContext ctxt, int index) {
return Padding(
padding: EdgeInsets.only(
top: MediaQuery.of(context).size.height / number,
),
child: Container(
height: 2.0,
width: MediaQuery.of(context).size.width,
color: Colors.red,
),
);
})

How can I make second widget in Stack widget is important?

I use Stack widget for making overlay.
Let's imagine that.
1) I add PageView at the Bottom.
2) I add Container to make Gradient at the Top.
I WANT TO KNOW THAT
How can I scroll PageView in spite of Gradient is over it?
This is a example
body: Stack(
children: <Widget>[
PageView.builder(
itemBuilder: (BuildContext context, int index) => Container(
height: double.infinity,
width: double.infinity,
child: Text("Index: $index"),
color: _pageColors[index],
),
onPageChanged: (number) {
setState(() {
_pageFocus = number + 1;
});
print(number);
},
controller: _pageController,
itemCount: _pageColors != null ? _pageColors.length : 0,
),
Align(
alignment: AlignmentDirectional.bottomEnd,
child: Container(
height: 100.0,
child: Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Color.fromRGBO(255, 255, 255, 0.0),
Colors.white,
],
stops: [
0.0,
3.0
],
begin: FractionalOffset.topCenter,
end: FractionalOffset.bottomCenter,
tileMode: TileMode.repeated),
),
width: double.infinity,
height: double.infinity,
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Align(
alignment: AlignmentDirectional.centerStart,
child: Text('$_pageFocus/${_pageColors.length}')),
)
],
),
),
),
],
),
See if wrapping the Align in an IgonorePointer helps. docs.flutter.io/flutter/widgets/IgnorePointer-class.html