Gridview.builder with Sticky headers - flutter

I am hella frustrated.
I need a Gridview.builder (or Listview with 3 Columns in each row)
AND on top of the Grid I need 1 Header.
Yet my code screws either the 3 Column List up, or the Header which will be tripled then.
I am a total coding newbie. Yet I am trying desperately to fix this issue.
Sorry for the wrong code in advance.
GridView.builder(
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,),
itemCount: 210,
itemBuilder: (context, index) {
return StickyHeader(
header: Container(
height: 50.0,
color: Colors.blueGrey[700],
padding: EdgeInsets.symmetric(horizontal: 16.0),
alignment: Alignment.centerLeft,
child: Text('Header',
style: const TextStyle(color: Colors.white),
),
),
content: Column(
children:
List<int>.generate(21, (index) => index)
.map((item) => Container(
decoration:
BoxDecoration( // <-- BoxDecoration
border: Border(bottom: BorderSide())
),
height: 50,
width: 5000000,
child: Text ('Test'),
))
.toList(),
),
);
}),

I would use a Column which first child is the header and the second one is the GridView inside an Expanded widget.
Something like this.
Or you can use slivers in a CustomScrollView. Short tutorial here.

Related

ListTiles inside ListView won't disappear on scrolling

I've got a ListView within a Column. In that Listview I want to place a couple of ListTiles. Unfortunately the tiles behave weird when scrolling. They are shown on top of the other widget placed in the Column
Is there a way to prevent that behaviour of ListTile?
Here is my code:
Column(children: [
const ChatHeader(),
Padding(
padding: const EdgeInsets.all(8),
child: SizedBox(
height: 300,
child: ListView.builder(
padding: const EdgeInsets.only(left: 8, right: 8),
scrollDirection: Axis.vertical,
itemCount: myCollection,
shrinkWrap: true,
physics: const BouncingScrollPhysics(),
itemBuilder: (BuildContext context, int index) {
var item = myCollection[index];
return Column(children: [
Row(
children: [
Container(
decoration: boxDecoration(
radius: 20, bgColor: d_colorPrimary)),
text("${item.value1}", fontSize: textSizeMedium)
],
),
ListTile(
dense: true,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8))),
tileColor: quiz_light_gray,
title: SizedBox(
child: text(item.name,
fontSize: textSizeMedium,
textColor: d_textColorPrimary,
isLongText: true,
maxLine: 10)))
]);
}))),
16.height,
Container(color: greenColor, child: Text("text input here"))
]);
Replacing the ListTiles with a Container solves this problem. As far as I can see there is no property to prevent that behaviour. Still want to use ListTiles.
Perhaps this is because of the usage of BouncingScrollPhysics().
Try replacing it with Neverscrollablescrollphysics() or just wrap the whole Listview.builder with an Expanded widget. which will let you won't use shirnkWrap and physics properties.
If the Container widget fixes the issue then you can try wrapping Listile() with another Sizedbox() widget.
I've wrapped the SizedBox with the ListView in a Material widget. That solved the problem.

Flutter: FlexLayoutManager similar to the one in native android

So I'm trying to implement a flex listview similar to the google FlexLayoutManager to the horizontal axis with wrap, you can see an example in the wrap section
https://github.com/google/flexbox-layout/raw/main/assets/flex-wrap.gif
here is my code:
ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: categories.length,
padding: EdgeInsetsDirectional.only(start: 16, end: 12),
itemBuilder: (context, index) {
return InkWell(
onTap: (){
},
child: Container(
height: 24,
alignment: Alignment.center,
child: Text(
categories[index].name,
),
),
);
},
)
what I have to add to my listview to make the items wrap and move to the next row if they exceeded the screen width?
Not tested, but as I indicated in my comment, I'd use something like:
Wrap(
children: [
for (final c in categories)
InkWell(child: Text(c.name)),
]);
adding of course all your parameters, and the extra container.
As an alternative, you can use a GridView.builder instead of ListView.builder:
Creates a scrollable, 2D array of widgets that are created on demand.
result:
I have made my window very small and the children still wrap:
With the window maximized:
code:
GridView.builder(
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 200,
childAspectRatio: 3 / 2,
crossAxisSpacing: 20,
mainAxisSpacing: 20),
itemCount: _categories.length,
padding: EdgeInsetsDirectional.only(start: 16, end: 12),
itemBuilder: (context, index) {
return InkWell(
onTap: () {},
child: Container(
height: 24,
alignment: Alignment.center,
child: Text(
categories[index].name,
),
),
);
},
)

I tried to wrap column with Singlechildscrollview Flutter but screen goes blank

[enter image description here][1]
Inside My column, there is a stack, a carousel slider,a gridview builder. I want to scroll all of them together. I tried to use singlechildscrollview as you can see in the code below. Please Someone help me how can I scroll those things together.
[1]: https://i.stack.imgur.com/FYexC.png` enter code here`
Scaffold(
backgroundColor: Colors.orange,
// Color(0xFFFFF176),
body: SingleChildScrollView(
child: Column(
children: [
Expanded(
child: Stack(
alignment: Alignment.bottomCenter,
children: [
CarouselSlider(
items: slideImage
.map((image) =>
Builder(builder: (BuildContext context) {
return Container(
height: 200,
width: 500,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(40),
image: DecorationImage(
image: AssetImage(image),
fit: BoxFit.fill),
),
);
}))
.toList(),
options: CarouselOptions(
onPageChanged: (index, reason) {
setState(() {
activeIndex = index;
});
},
height: 300,
viewportFraction: 1,
autoPlay: true,
),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: AnimatedSmoothIndicator(
activeIndex: activeIndex, count: slideImage.length),
),
],
),
),
SizedBox(
height: 10,
),
Expanded(
child: GridView.builder(
shrinkWrap: true,
// physics: NeverScrollableScrollPhysics(),
itemCount: menuImage.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 0.8,
crossAxisSpacing: 8,
mainAxisSpacing: 8,
),
itemBuilder: (context, index) => Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
color: Color(0xFFFFFDE7),
elevation: 10,
child: GridTile(
child: Column(
children: [
Image.asset(
menuImage[index],
fit: BoxFit.fill,
),
Text(
title[index],
style: TextStyle(fontSize: 18),
),
],
),
),
),
),
),
],
),
),
);
}
}
It would be best if you gave height to the column you are using singlechildeScrollview.
Wrap column widget in container or sizedbox widget and give it height.
column widget has children widget GridView.builder that is wrapped in expanded so gridview.builder will try to take all available height in the column which will be infinite because it's not defined and you will get column covering screen taking infinite screen height in short blank screen.
In flutter, Column will take height as much as it can, SingleChildScrollView child dont have height (infinite). Combine together, Flutter don't know how to render them correctly and causing error.
To solve it, try to determine the height of Column by widgget like SizedBox or determine the mainSize.min.
Another way to solve it is wrap Column by IntrinsicHeight but not recommend cause it heavy.
If it takes too much height. so give height to the column.
like this..
SingleChildScrollView(
child: SizedBox(
height: 500,
child: Column(
children: const [...],
),
),
)
your expanded widget is taking whole space of column try removing it or replacing it with Sizedbox.

Problem to separate listView.Builder into two lines

I've been trying to modify my flutter code to display product-categories on two lines.
In the current model, you can view the categories without any problem by dragging them to the side (only one line). However, for ease of future customer-viewer, I would like to split it into two lines.
my current ListView.builder displays like this:
Click Here
I would like it to display as follows: Click Here
Here is my code:
Row(
children: [
Expanded(
child: SizedBox(
height: 80,
child: category.categoryList != null ? category.categoryList.length > 0 ? ListView.builder(
itemCount: category.categoryList.length,
padding: EdgeInsets.only(left: Dimensions.PADDING_SIZE_SMALL),
physics: BouncingScrollPhysics(),
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
return Padding(
padding: EdgeInsets.only(right: Dimensions.PADDING_SIZE_SMALL),
child: InkWell(
onTap: () => Navigator.pushNamed(context, Routes.getCategoryRoute(
category.categoryList[index].id, category.categoryList[index].image,
category.categoryList[index].name.replaceAll(' ', '-'),
)),
child: Column(children: [
ClipOval(
child: FadeInImage.assetNetwork(
placeholder: Images.placeholder_image,
image: Provider.of<SplashProvider>(context, listen: false).baseUrls != null
? '${Provider.of<SplashProvider>(context, listen: false).baseUrls.categoryImageUrl}/${category.categoryList[index].image}':'',
width: 65, height: 65, fit: BoxFit.cover,
),
),
Text(
category.categoryList[index].name,
style: rubikMedium.copyWith(fontSize: Dimensions.FONT_SIZE_SMALL),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
]),
),
);
},
) : Center(child: Text(getTranslated('no_category_avl', context))) : CategoryShimmer(),
),
),
ResponsiveHelper.isMobile(context)? SizedBox(): category.categoryList != null ? Column(
children: [
InkWell(
onTap: (){
showDialog(context: context, builder: (con) => Dialog(
child: Container(height: 550, width: 600, child: CategoryPopUp())
));
},
child: Padding(
padding: EdgeInsets.only(right: Dimensions.PADDING_SIZE_SMALL),
child: CircleAvatar(
radius: 35,
backgroundColor: Theme.of(context).primaryColor,
child: Text(getTranslated('view_all', context), style: TextStyle(fontSize: 14,color: Colors.white)),
),
),
),
SizedBox(height: 10,)
],
): CategoryAllShimmer()
],
),
If anyone can help me, I will be very grateful. Big hug!
There are 2 possibilities I can think of
Solution 1:
You can have 2 list views one on the top and one on the bottom. (1st row having half and the 2nd row having another half)
First row: itemCount: half, and inside builder you can use index as it is
Second row: itemCount: half, and inside builder you can use index as index+half (as builder always starts from 0)
*Above solution might be a tough choice if you have the category items more than 10 (which again leads to scrolling)
Solution 2:
You can use a "GridView"
Below is a link where you can go through to know how you can build in GridView.
Link: https://stackoverflow.com/a/44184514/10136829
Hope this answers is helpful.

Flutter "NoSuchMethodError: The getter 'position' was called on null" when sticky header is used to wrap around GirdView.builder widget

Trying to use sticky header to wrap around a GridView.builder widget, because I want to have a header follow when the user scrolls down enough the screen, but getting "NoSuchMethodError: The getter 'position' was called on null. Receiver: null Tried calling: position See also: https://flutter.dev/docs/testing/errors". I use this same widget to wrap around a Column widget. I tried wrapping the GridView with Container, Column and other widgets. I would just get other errors. What does this error mean?
return _stickyHeader.render(
headerChild: Text(''),
content: GridView.builder(
shrinkWrap: true,
physics: ScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 5.0,
mainAxisSpacing: 5.0,
),
itemCount: state.avatarUrlList.length,
itemBuilder: (BuildContext context, int index) {
if (index == state.currentSelectedAvatarIndex) {
return Center(
child: InkWell(
onTap: () => _onAvatarImageClicked(
state.avatarUrlList[index], index),
child: Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color: Colors.red,
width: 4.0,
),
),
child: CircleAvatar(
radius: 60,
backgroundColor: Colors.transparent,
backgroundImage:
NetworkImage(state.avatarUrlList[index]),
),
),
),
);
} else {
return Center(
child: InkWell(
onTap: () => _onAvatarImageClicked(
state.avatarUrlList[index], index),
child: CircleAvatar(
radius: 60,
backgroundColor: Colors.transparent,
backgroundImage:
NetworkImage(state.avatarUrlList[index]),
),
),
);
}
},
),
);
}
Widget render({Widget headerChild, Widget content}) {
return StickyHeader(
header: Container(
decoration: BoxDecoration(
color: ThemeConstants.ceruleanCrayola,
borderRadius: BorderRadius.circular(15),
),
height: 50.0,
padding: EdgeInsets.symmetric(horizontal: 16.0),
margin: EdgeInsets.symmetric(horizontal: 20.0),
alignment: Alignment.centerLeft,
child: headerChild,
),
content: content,
);
}
Based on https://pub.dev/packages/sticky_headers
You can place a StickyHeader or StickyHeaderBuilder inside any scrollable content, such as: ListView, GridView, CustomScrollView, SingleChildScrollView or similar.
You may need to try put your StickyHeader to SingleChildScrollView for basic.