Container with drop shadow containing a dynamic GridView - flutter

So a design requires Containing a GridView of profiles that is dynamic in size.
The one I came up with is something like this:
class Applicants extends StatelessWidget {
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Container(
padding: EdgeInsets.all(20),
child: GridView.builder(
clipBehavior: Clip.none,
itemCount: 10,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
),
itemBuilder: (context, index) => _buildBox(context, index),
),
),
),
],
);
}
}
But how do I put them in a Container with a drop shadow that extends with GridView? This list is populated from DB and my attempts of placing the GridView in a Container with DropShadow always fail.

An easy way is using Card and use elevation.
Widget _buildBox(BuildContext context, int index) {
return Card(
elevation: 12,
child: Center(
child: Text("Applicant"),
),
);
}

Related

flutter GridView.builder won't let rest of screen scroll

I have GridView.builder middle of my screen but it does not let my screen to scroll! I must find some white space in screen in order to be able to scroll rest of my screen.
Here is how my screen structure looks like:
Widget build(BuildContext context) {
return Scaffold(
appBar: const TopBarFile(),
drawer: const DrawerFile(),
body: SafeArea(
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(12.0),
child: FutureBuilder(
future: myCards,
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// some widgets...
const SizedBox(height: 15),
// here middle of screen is GridView
SizedBox(
child: GridView.builder(
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
),
shrinkWrap: true,
itemCount: snapshot.data['cards'].length,
itemBuilder: (BuildContext context, int index) {
return InkWell(...);
}
)
),
const SizedBox(height: 15),
// some more widgets...
]
);
} else {...}
return container();
}
),
),
),
),
),
}
Note: this grid view only has 6 items so I don't need it to be scrollable actually I just use it for design purpose but its causing scrolling issue, so I just need to be able to scroll my page even if I'm touching on top of this grid view items.
Any suggestions?
you can define a physics property with NeverScrollableScrollPhysics() value inside GridView, this will solve the issue. Always use physics property When you have nested scrollable widget.
You can give physics: NeverScrollableScrollPhysics() to GridView() or use Wrap() widget instead of GridView().
Use physics and shrinkWrap property as below:
SizedBox(
child: GridView.builder(
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
),
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: snapshot.data['cards'].length,
itemBuilder: (BuildContext context, int index) {
return InkWell(...);
}
)
),

Issues with GridView for the following UI

I am trying to construct the following UI, but having issues with that. More specifically I tried different ways of doing this with GridView, but had no luck since I was not able to switch from 2 to 1 for crossAxisCount, because after showing the favorite cakes I need to "come back" to "normal" and show one block on one line for "Similar Products". Here is what I tried:
body: new LayoutBuilder(
builder: (context, constraint) {
return Padding(
padding: const EdgeInsets.fromLTRB(8.0, 0, 8.0, 0),
child: new GridView(
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: constraint.maxWidth / constraint.maxHeight,
),
children: <Widget>[
// those widgets here will be created dynamically at the end
// manually created a few just for illustration
new MyFavoriteWidget(),
new MyFavoriteWidget(),
new MyFavoriteWidget(),
new MyFavoriteWidget(),
new MyFavoriteWidget(),
new MyFavoriteWidget(),
new MyFavoriteWidget(),
new MyFavoriteWidget(),
new Container(
child: Text("Similar Products"),
),
// same for those widgets
new SimilarProductWidget(),
new SimilarProductWidget(),
new SimilarProductWidget(),
new SimilarProductWidget(),
],
),
);
},
),
But this renders just 2 columns, which is what I want for the top part, but after the list of MyFavoriteWidget() I need to switch to normal layout and have one block on one line. And if I take this part out of the GridView it won't be visible. I feel like GridView is still the best way of implementing this but was not able to find a way around it. Even a skeleton code to get started or a hint how to overcome this issue will be much helpful.
I offer you try this code. For top list use GridView.count and for bottom list use ListView.builder. I give you a simple example to understand it. Run code below and see the result.
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Your heading'),
),
body: SafeArea(
child: ListView(
shrinkWrap: true,
physics: ScrollPhysics(),
children: [
GridView.count(
crossAxisCount: 2,
scrollDirection: Axis.vertical,
physics: ScrollPhysics(),
shrinkWrap: true,
children: List.generate(
6,
(index) => Container(
margin: EdgeInsets.all(10),
width: 50,
height: 50,
color: Colors.yellow,
),
),
),
ListView.builder(
physics: ScrollPhysics(),
shrinkWrap: true,
scrollDirection: Axis.vertical,
itemCount: 10,
itemBuilder: (BuildContext context, int index) {
return Card(
color: Colors.red,
child: Container(
height: 70,
margin: EdgeInsets.all(30),
width: double.infinity,
),
);
},
),
],
)));
}

Flutter: How can I use DraggableScrollableActuator.reset AND the ScrollController from DraggableScrollableSheet for a nested list?

I am getting this error.
The following assertion was thrown building _InheritedResetNotifier(dirty):
flutter: ScrollController attached to multiple scroll views.
flutter: 'package:flutter/src/widgets/scroll_controller.dart':
flutter: Failed assertion: line 111 pos 12: '_positions.length == 1'
It seems I can either attach DraggableScrollableSheet's ScrollController to the nested list OR use DraggableScrollableActuator.reset(context) to reset the extent. I don't see why I can't do both. Is this a bug? Is there a work around or another way?
Here is my code:
class InterfaceSelector extends StatefulWidget {
#override
InterfaceSelectorState createState() => InterfaceSelectorState();
}
class InterfaceSelectorState extends State<InterfaceSelector> {
double initialChildSize = 0.5;
double minChildSize = 0.5;
double maxChildSize = 0.7;
#override
Widget build(BuildContext context) {
return DraggableScrollableActuator(
child: DraggableScrollableSheet(
initialChildSize: initialChildSize,
minChildSize: minChildSize,
maxChildSize: maxChildSize,
builder: (BuildContext ctx, ScrollController scrollController) {
return SingleChildScrollView(
controller: scrollController,
child: Container(
height: MediaQuery.of(context).size.longestSide * .7,
color: Theme.of(ctx).primaryColor,
child: DefaultTabController(
length: 4,
child: Column(
children: <Widget>[
Material(
color: Theme.of(ctx).accentColor,
child: TabBar(
tabs: [
Tab(text: "One"),
Tab(text: "Two"),
Tab(text: "Three"),
Tab(text: "Four"),
],
),
),
Expanded(
child: TabBarView(
children: [
One(),
Two(),
Three(scrollController),
Four(),
],
),
),
],
),
),
),
);
},
),
);
}
}
class Three extends StatefulWidget {
ScrollController scrollController;
Three(this.scrollController);
#override
_ThreeState createState() => _ThreeState();
}
class _ThreeState extends State<Three> with AutomaticKeepAliveClientMixin {
#override
bool get wantKeepAlive => true;
#override
Widget build(BuildContext context) {
Stuff stuff = Provider.of<Stuff>(context);
return Column(
children: <Widget>[
MaterialButton(onPressed: () {
DraggableScrollableActuator.reset(context);
}),
Expanded(
child: GridView.builder(
controller: widget.scrollController,
padding: const EdgeInsets.all(10),
itemCount: stuff.all.length,
itemBuilder: (ctx, i) => ChangeNotifierProvider.value(
value: stuff.all[i],
key: UniqueKey(),
child: StuffCard(i, stuff.all[i], stuff),
),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
),
),
),
],
);
}
}
Your GridView doesn't need scrolling - scrolling is provided by your SingleChildScrollView. Don't pass the scrollController to GridView, set physics: NeverScrollableScrollPhysics(), in your grid builder instead:
GridView.builder(
physics: NeverScrollableScrollPhysics(),
padding: const EdgeInsets.all(10),
itemCount: stuff.all.length,
itemBuilder: (ctx, i) => ChangeNotifierProvider.value(
value: stuff.all[i],
key: UniqueKey(),
child: StuffCard(i, stuff.all[i], stuff),
),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
),
),

Dynamic staggered grid with same cell height in flutter

GridView List
I'm trying to make Staggered Grid List with same image cell height
I found a plugin https://pub.dev/packages/flutter_staggered_grid_view but it didn't work for me,
I need 2nd column to get down with some space and column height should be same, what should I do?
flutter_staggered_grid_view Plugin.
Try this:
class MyHomeScreen extends StatefulWidget {
#override
_MyHomeScreenState createState() => _MyHomeScreenState();
}
class _MyHomeScreenState extends State<MyHomeScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Staggered Grid View with image demo"),),
body: Center(
child: sliverGridWidget(context),
),
);
}
Widget sliverGridWidget(BuildContext context){
return StaggeredGridView.countBuilder(
padding: const EdgeInsets.all(8.0),
crossAxisCount: 4,
itemCount: 10, //staticData.length,
itemBuilder: (context, index){
return Card(
elevation: 8.0,
child:InkWell(
child: Hero(
tag: index,// staticData[index].images,
child: new FadeInImage(
width: MediaQuery.of(context).size.width,
image: NetworkImage("https://images.unsplash.com/photo-1468327768560-75b778cbb551?ixlib=rb-1.2.1&w=1000&q=80"), // NetworkImage(staticData[index].images),
fit: BoxFit.cover,
placeholder: AssetImage("assets/images/app_logo.png"),
),
),
onTap: (){
//
}
)
);
},
staggeredTileBuilder: (index) => StaggeredTile.count(2,index.isEven ? 2: 3),
mainAxisSpacing: 8.0,
crossAxisSpacing: 8.0,
);
}
}
Output:

Flutter remove space between GridView row

I am trying to create a gridview of raised buttons but there is a large amount of space between the rows of of the grid like this picture:
I am implementing the GridView with the code at the bottom of the page:
As you can see I set:
SliverGridDelegateWithMaxCrossAxisExtent(maxCrossAxisExtent: 150, mainAxisSpacing: 4, crossAxisSpacing: 4),
I would have expected that setting the main axis spacing and cross axis spacing should remove those spaces.
I also tried returning the gridview in a sized box and changing it to SliverGridWithFixedCount, but nothing seems to be changing it.
I am not sure what I have done incorrectly in the layout?
Thanks for your help
body: Column(
children: <Widget>[
Flexible(
child: filtersGridView(),
),
],
),
);
}
}
class filtersGridView extends StatefulWidget {
#override
_filtersGridViewState createState() => _filtersGridViewState();
}
class _filtersGridViewState extends State<filtersGridView> {
final List <DocumentSnapshot> documents;
_filtersGridViewState({this.documents});
#override
Widget build(BuildContext context) {
return StreamBuilder(
stream: Firestore.instance.collection('categories').snapshots(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return Center(child: const Text('Loading events...'));
}
return GridView.builder(
gridDelegate:
SliverGridDelegateWithMaxCrossAxisExtent(maxCrossAxisExtent: 150, mainAxisSpacing: 4, crossAxisSpacing: 4),
itemBuilder: (BuildContext context, int index) {
return Column(children: <Widget>[
InkWell(
onTap: () {
},
child: SizedBox(
height: 30,
child: RaisedButton(
color: Colors.white,
child: Row(
children: <Widget>[
Text(snapshot.data.documents[index]['name'].toString(), textAlign: TextAlign.center, style: TextStyle(fontSize: 15, color: Colors.black,),),
],
),
If you are concerned about the padding inside of the buttons - it happens due to the minimum width setting of the material buttons being set to 88.
Also, in my experience I noticed that material buttons have some weird margin around them. I solved that with materialTapTargetSize: MaterialTapTargetSize.shrinkWrap.
ButtonTheme(
minWidth: 0,
height: 30,
child: RaisedButton(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
// ...
)
)
If you want the buttons to fill the entire maxCrossAxisExtent in height - use RawMaterialButton with custom constraints assigned.
Updated
I assumed the problem is within the buttons, but it just occurred to me that it is in fact about the GridView Delegate.
How SliverGridDelegateWithMaxCrossAxisExtent works as per Flutter docs:
This delegate creates grids with equally sized and spaced tiles.
The default value for childAspectRatio property of the delegate is 1.0, i.e. - a square. You are getting a perfectly logical layout displayed - grid of 1:1 blocks.
To solve this you need to come up with the right childAspectRatio value.
Some pseudocode: cellHeight = cellWidth / childAspectRatio.
e.g.
childAspectRatio: 2 will display cells sized as following:
2
-----------------
| |
| | 1
| |
-----------------
Please let me know if this helped.
Try this hope so it will work,
GridView.builder(
itemCount: 6,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3,),
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
child: Flex(
direction: Axis.vertical,
children: <Widget>[
Expanded(flex: 5, child: InkWell(
onTap: (){},
)),
Expanded(
flex: 5,
child: RaisedButton(
onPressed: () {},
child: Text('Bt'),
))
],
),
),
);
},
),
increase the childAspectRatio value to 2,
primary: false,
scrollDirection: Axis.vertical,
// padding: const EdgeInsets.all(10),
crossAxisSpacing: 10,
mainAxisSpacing: 10,
maxCrossAxisExtent: 180.0,
shrinkWrap: true,
childAspectRatio: 2,
children: <Widget>[
container(),
container(),
container(),
])