How to vertical align ListView in the middle - dart

I want my list item in the middle of the ListView
#override Widget build(BuildContext context)
{
List<String> listName = ['Woody', 'Buzz', 'Rex'];
return Container
(
decoration: BoxDecoration(border: Border.all(color: Colors.pinkAccent)),
width: 400,
height: 700,
alignment: Alignment.centerLeft,
child: ListView.builder
(
itemCount: listName.length,
itemBuilder: (context, index)
{
return OurName(listName[index]);
},
),
);
}
This is when I use shrinkWrap, when I scroll up it's cut off and it can't be scroll down
shrinkWrap
This is what I expected expected

The key to your issue is the shrinkWrap property of ListView. So to fix this you can do something like this:
Container(
alignment: Alignment.centerLeft,
child: ListView.builder(
itemBuilder: (context, index) {
return Text("The index$index");
},
shrinkWrap: true,
itemCount: 30,
),
),

For me works this code!
#override
Widget build(BuildContext context) {
return Container(
height: double.infinity,
width: double.infinity,
alignment: Alignment.center,
child: ListView.builder(
shrinkWrap: true,
itemCount:rows.length,
itemBuilder: (
context,
index,
) {
return ...;
}),
);
}

I came here to center vertically (and horizontally) my listView, and came up with this:
#override
Widget build(BuildContext context) {
List<String> listName = ['Woody', 'Buzz', 'Rex'];
return Align(
child: ListView.builder(
itemCount: listName.length,
itemBuilder: (context, index) {
return Center(child: Text(listName[index]));
},
shrinkWrap: true,
),
);
}

i dont get what you mean do you want to align the whole listview then use a center widget and align the listview in the center, or use Align widget and manually align it by
Align(
alignment: Alignment.centerRight,
child: //here your list,
)
if thats not what you want or doesn't get the job done then please explain more.

Related

Widget inside a column not scrolling completely when scrolling Scroll-able widget

I have a NestedScrollView whose body contains a TabBarView. And one of the tabs has a column with an image and a scrollable widget(GridView.builder). When scrolling this scrollable widget, the images get stuck halfway(as if it was pinned in that position).
Here's the code
//home.dart
class _HomePage extends State<HomePage> {
#override
Widget build(BuildContext context) {
return Container( //this is the image that gets stuck
child: Column(
children: <Widget>[
new Container(
child: new Image.asset(
"images/product.jpg",
fit: BoxFit.fitWidth,
),
),
Expanded(
child: FreshFinds(), //this is the scrollable widget
),
],
),
);
}
}
// Freshfind.dart
#override
Widget build(BuildContext context) {
return Card(
child: GridView.builder(
// shrinkWrap: true,
itemCount: 50,
physics: ScrollPhysics(),
gridDelegate:
new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
itemBuilder: (BuildContext context, int index) {
return FutureBuilder(
future: fetchdata(index),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData)
return buildfake(index);
else
return buildcard(snapshot.data, index);
},
);
},
),
);
}
Here is a video of the problem
I think you need to use SliverAppBar() widget alongside with TabBar().
Here's a resource that might help you

Don't center a PageView - Flutter

I am currently using the carousel-slider library to get a carousel in Flutter.
This library is based on a PageView, and in a PageView the elements are centered.
That's the carousel I get:
And this is what I'd like to have:
Here is the code where is use the CarouselSlider:
CarouselSlider(
height: 150,
viewportFraction: 0.5,
initialPage: 0,
enableInfiniteScroll: false,
items: widget.user.lastGamesPlayed.map((game) {
return Builder(
builder: (BuildContext context) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 10),
child: GestureDetector(
onTap: () {
game.presentGame(context, widget.user);
},
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(25)),
child: Container(
color: Theme.MyColors.lightBlue,
child: Center(
child: Padding(
padding: EdgeInsets.all(20),
child: AutoSizeText(game.name,
style: TextStyle(fontSize: 70),
maxLines: 1)),
),
))));
},
);
}).toList(),
)
And here is the code inside the CarouselSlider library:
#override
Widget build(BuildContext context) {
return getWrapper(PageView.builder(
physics: widget.isScrollEnabled
? AlwaysScrollableScrollPhysics()
: NeverScrollableScrollPhysics(),
scrollDirection: widget.scrollDirection,
controller: widget.pageController,
reverse: widget.reverse,
itemCount: widget.enableInfiniteScroll ? null : widget.items.length,
onPageChanged: (int index) {
int currentPage =
_getRealIndex(index, widget.realPage, widget.items.length);
if (widget.onPageChanged != null) {
widget.onPageChanged(currentPage);
}
},
itemBuilder: (BuildContext context, int i) {
final int index = _getRealIndex(
i + widget.initialPage, widget.realPage, widget.items.length);
return AnimatedBuilder(
animation: widget.pageController,
child: widget.items[index],
builder: (BuildContext context, child) {
// on the first render, the pageController.page is null,
// this is a dirty hack
if (widget.pageController.position.minScrollExtent == null ||
widget.pageController.position.maxScrollExtent == null) {
Future.delayed(Duration(microseconds: 1), () {
setState(() {});
});
return Container();
}
double value = widget.pageController.page - i;
value = (1 - (value.abs() * 0.3)).clamp(0.0, 1.0);
final double height = widget.height ??
MediaQuery.of(context).size.width * (1 / widget.aspectRatio);
final double distortionValue = widget.enlargeCenterPage
? Curves.easeOut.transform(value)
: 1.0;
if (widget.scrollDirection == Axis.horizontal) {
return Center(
child:
SizedBox(height: distortionValue * height, child: child));
} else {
return Center(
child: SizedBox(
width:
distortionValue * MediaQuery.of(context).size.width,
child: child));
}
},
);
},
));
}
How can I prevent elements from being centered?
Thank you in advance
If you don't want to animate page size over scroll there is no need to use this carousel-slider library.
Also, PageView is not the best Widget to achieve the layout you want, you should use a horizontal ListView with PageScrollPhysics.
import 'package:flutter/material.dart';
class Carousel extends StatelessWidget {
Carousel({
Key key,
#required this.items,
#required this.builderFunction,
#required this.height,
this.dividerIndent = 10,
}) : super(key: key);
final List<dynamic> items;
final double dividerIndent;
final Function(BuildContext context, dynamic item) builderFunction;
final double height;
#override
Widget build(BuildContext context) {
return Container(
height: height,
child: ListView.separated(
physics: PageScrollPhysics(),
separatorBuilder: (context, index) => Divider(
indent: dividerIndent,
),
scrollDirection: Axis.horizontal,
itemCount: items.length,
itemBuilder: (context, index) {
Widget item = builderFunction(context, items[index]);
if (index == 0) {
return Padding(
child: item,
padding: EdgeInsets.only(left: dividerIndent),
);
} else if (index == items.length - 1) {
return Padding(
child: item,
padding: EdgeInsets.only(right: dividerIndent),
);
}
return item;
}),
);
}
}
Usage
Carousel(
height: 150,
items: widget.user.lastGamesPlayed,
builderFunction: (context, item) {
return ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(25)),
child: Container(
width: 200,
color: Theme.MyColors.lightBlue,
child: Center(
child: Padding(
padding: EdgeInsets.all(20),
child: AutoSizeText(
item.name,
style: TextStyle(fontSize: 70),
maxLines: 1,
),
),
),
),
);
},
)
UPDATE
As observed by #AdamK, my solution doesn't have the same scroll physics behavior as a PageView, it acts more like a horizontal ListView.
If you are looking for this pagination behavior you should consider to write a custom ScrollPhysics and use it on your scrollable widget.
This is a very well explained article that helps us to achieve the desired effect.

Strange Bug with horizontal ListView inside Vertical SliverList

After scrolling vertically upwards, the horizontal ListView scrolls itself to the right.
The error only occurs when, at the time the horizontal Listview is displayed, the finger no longer touches the touchscreen and the vertical SliverList continues to run by itself.
Here is the code to reproduce the error:
Widget build(BuildContext context) {
return CustomScrollView(
slivers: <Widget>[
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
if (index == 0)
return SizedBox(
height: 50,
child: ListView.builder(
itemBuilder: (context, index) => Container(
width: 200,
color: Colors.black45,
margin: const EdgeInsets.symmetric(horizontal: 8),
),
scrollDirection: Axis.horizontal,
),
);
return Container(
height: 200,
margin: const EdgeInsets.symmetric(vertical: 8),
color: Colors.black45,
);
},
),
)
],
);
}
You should add the key to your ListView.
In here, we can use key: PageStorageKey()

Scrollable flutter popup menu

I'm trying to use flutter popup menu button, but I can't seem to make it smaller with a scroll.
Is it doable? Or am I using the wrong widget to do it?
Image below as reference, would like to show only the first 4 / 5 items, and scroll to show the rest!
Thanks in advance!
You can create your own PopUp Widget instead.
A Card wrapped into a AnimatedContainer with specific dimensions and a ListView inside.
Place this widget on your screen using Stack and Positioned widgets so it will be above other elements on the top | right.
class CustomPopup extends StatefulWidget {
CustomPopup({
#required this.show,
#required this.items,
#required this.builderFunction,
});
final bool show;
final List<dynamic> items;
final Function(BuildContext context, dynamic item) builderFunction;
#override
_CustomPopupState createState() => _CustomPopupState();
}
class _CustomPopupState extends State<CustomPopup> {
#override
Widget build(BuildContext context) {
return Offstage(
offstage: !widget.show,
child: AnimatedContainer(
duration: Duration(milliseconds: 300),
height: widget.show ? MediaQuery.of(context).size.height / 3 : 0,
width: MediaQuery.of(context).size.width / 3,
child: Card(
elevation: 3,
child: MediaQuery.removePadding(
context: context,
removeTop: true,
child: ListView.builder(
scrollDirection: Axis.vertical,
itemCount: widget.items.length,
itemBuilder: (context, index) {
Widget item = widget.builderFunction(
context,
widget.items[index],
);
return item;
},
),
),
),
),
);
}
}
return Stack(
children: <Widget>[
Container(
color: Colors.blueAccent,
),
Positioned(
right: 0,
top: 60,
child: CustomPopup(
show: shouldShow,
items: [1, 2, 3, 4, 5, 6, 7, 8],
builderFunction: (context, item) {
return ListTile(
title: Text(item.toString()),
onTap: () {}
);
},
),
),
],
);
You can create this in two ways: the first one is PopupMenuButton widget and the second one is PopupRoute.
class HomePage extends StatefulWidget {
#override
_HomepageState createState() => _HomepageState();
}
class _HomepageState extends State {
Listitems = [1,2,3,4,5,6,7,8,9,10,11,12,13];
#override
Widget build(BuildContext context) {
return Scaffold(body: Center(
child: PopupMenuButton(
child: Icon(Icons.add_shopping_cart),
offset: Offset(-1.0, -220.0),
elevation: 0,
color: Colors.transparent,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10))),
itemBuilder: (context) {
return <PopupMenuEntry<Widget>>[
PopupMenuItem<Widget>(
child: Container(
decoration: ShapeDecoration(
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10))),
child: Scrollbar(
child: ListView.builder(
padding: EdgeInsets.only(top: 20),
itemCount: items.length,
itemBuilder: (context, index) {
final trans = items[index];
return ListTile(
title: Text(
trans.toString(),
style: TextStyle(
fontSize: 16,
),
),
onTap: () {
//what would you like to do?
},
);
},
),
),
height: 250,
width: 500,
),
)
];
}),
)
You can also adjust the number of items you want to show by reducing or increasing height of the container. I also added a scrollbar just in case.
You can use maxHeight for constrains property.
...
PopupMenuButton(
constraints:
BoxConstraints(minWidth: context.maxWidth, maxHeight: 300),
...

Flutter scrollable body with horizontal list and grid as children

I'm having a hard time understanding how to best create a scrollable container for the body that holds inside children that by default are scrollable as well.
In this case the grid shouldn't scroll but it's the entire page that should scroll so you are able to see more of the elements inside the grid. So basically the whole content should move vertically with the addition of the ListView moving horizontally (but that works fine already)
I had it working but it was using a bunch of "silver" widget, and I'm hoping there's a better solution that works without using all those extra widgets.
Thanks
Here's my code so far:
class GenresAndMoodsPage extends AbstractPage {
#override
String getTitle() => 'Genres & Moods';
#override
int getPageBottomBarIndex() => BottomBarItems.Browse.index;
static const kListHeight = 150.0;
Widget _buildHorizontalList() => SizedBox(
height: kListHeight,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 20,
itemBuilder: (_, index) =>
CTile(heading: 'Hip Hop', subheading: '623 Beats'),
),
);
Widget _buildGrid() => GridView.count(
crossAxisCount: 2,
crossAxisSpacing: LayoutSpacing.sm,
mainAxisSpacing: LayoutSpacing.sm,
children: List.generate(10, (index) {
return CTile(
padding: false,
heading: 'Kevin Gates Type Beat',
subheading: '623 FOLLOWERS',
width: double.infinity,
);
}),
);
#override
Widget buildBody(_) {
return ListView(children: [
CSectionHeading('Popular Genres & Moods'),
_buildHorizontalList(),
CSectionHeading('All Genres & Moods'),
_buildGrid(),
]);
}
}
The result should be something like this
Create List with Horizontal Scroll direction and called it as a child for Vertical Scroll direction.
body: new ListView.builder(itemBuilder: (context, index){
return new HorizList();
})
class HorizList extends StatelessWidget{
#override
Widget build(BuildContext context) {
return new Container(
height: 100.0,
child: new ListView.builder(itemBuilder: (context, index){
return new Card(child: new Container(width: 80.0,
child: new Text('Hello'),alignment: Alignment.center,));
}, scrollDirection: Axis.horizontal,),
);
}
}
As we want Popular Genres & Moods section also to scroll, we should not using nestedScroll. In above example GridView is nested inside `ListView. Because of which when we scroll, only the GridView will scroll.
I used Only one ListView to achieve the similar screen.
Number of children = (AllGenresAndMoodsCount/2) + 1
divide by 2 as we are having 2 elements per row
+1 for the first element which is horizontal scroll view.
Please refer the code:
import 'package:flutter/material.dart';
void main() {
runApp(new Home());
}
class Home extends StatelessWidget {
#override
Widget build(BuildContext context) {
var image = new Image.network("http://www.gstatic.com/webp/gallery/1.jpg");
var container = new Container(
child: image,
padding: EdgeInsets.only(left: 5.0, right: 5.0, top: 5.0, bottom: 5.0),
width: 200.0,
height: 200.0,
);
return MaterialApp(
title: "Scroller",
home: Scaffold(
body: Center(
child: new ListView.builder(
itemBuilder: (context, index) {
if (index == 0) { //first row is horizontal scroll
var singleChildScrollView = SingleChildScrollView(
child: Row(
children: <Widget>[
container,
container,
container,
],
),
scrollDirection: Axis.horizontal);
return singleChildScrollView;
} else {
return new Row(
children: <Widget>[container, container],
);
}
},
itemCount: 10, // 9 rows of AllGenresAndMoods + 1 row of PopularGenresAndMoods
)),
),
);
}
}

Resources