Both Listview and Gridview needs height to be shown into our app.
But each model of phone has different size as height so it is impossible to define static height of the parent container of the list.
What I need to put as height for the container once use listview and gridview to cover all the phone model ?
Code:
Container(
height: 500,
child: GridView.builder(
itemCount: 20,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
),
itemBuilder: (BuildContext context, int index){
return GestureDetector(
onTap: () => showDialog(
context: context, builder: (context) => AlertDialog(
actions: [
Image.asset(widget.user.imageUrl),
Text(widget.user.name),
],
)
),
child: Card(
elevation: 5,
child: Image.asset(widget.user.imageUrl),
),
);
},
),
),
in this specific case height is 500 and it is good for some mobile phone but for other no, please let me know.
You can use screen height width for make it responsive according to devices:
height: MediaQuery.of(context).size.height * 0.1 //It takes 1 of 10 proportion of screen height
width: MediaQuery.of(context).size.width* 0.2 //It takes 2 of 10 proportion of screen width
You can place your GridView or ListView inside Expanded widget. The Expanded widget will take all the available space & you can easily show your GridView or ListView widget.
This solution will work on multiple screen sizes also without any problem because it will occupy the available space on its own.
Column(
children: [
// Any other widget
Expanded(
child: GridView.builder(
itemCount: 20,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
),
itemBuilder: (BuildContext context, int index){
return GestureDetector(
onTap: () => showDialog(
context: context, builder: (context) => AlertDialog(
actions: [
Image.asset(widget.user.imageUrl),
Text(widget.user.name),
],
),
),
child: Card(
elevation: 5,
child: Image.asset(widget.user.imageUrl),
),
);
},
),
),
// Any other widget
],
),
Related
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(...);
}
)
),
I have several containiers inside a ListView which will result in a scrollable content within a page. Each container has a Column as child and within the Column I have a title and a divider, then the actual content.
I want one of the container to be something like:
Title
--------- (divider)
Scrollable content (most likely a ListView)
What I have so far:
Container(
height: 250,
child: Column(children: <Widget>[
Text('Title'),
Divider(),
SingleChildScrollView(
child: ListView.builder(
shrinkWrap: true,
itemCount: 15,
itemBuilder: (BuildContext context, int index) {
return Text('abc');
}
)
)
]
)
The thing is that I want the container to have a specific height, but I get an overflow pixel error.
Wrap your ListView with Expanded. Remove your SingleChildScrollView as ListView has its own scrolling behaviour. Try as follows:
Container(
height: 250,
child: Column(children: <Widget>[
Text('Title'),
Divider(),
Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: 15,
itemBuilder: (BuildContext context, int index) {
return Text('abc');
}
),
)
]
))
Wrap your ListView.builder() widget inside a SizedBox() widget and specify available height after accommodating Title() widget.
Container(
height: 250,
child: Column(children: <Widget>[
Text('Title'),
Divider(),
SizedBox(
height: 200, // (250 - 50) where 50 units for other widgets
child: SingleChildScrollView(
child: ListView.builder(
shrinkWrap: true,
itemCount: 15,
itemBuilder: (BuildContext context, int index) {
return Text('abc');
}
)
)
)
]
)
You can also use Container() widget instead SizedBox() widget but only if needed.
SizedBox() is a const constructor where Container() widget is not, so SizedBox() allows the compiler to create more efficient code.
I am creating a gridview of images using future but during scrolling of gridview app crashes and there is not error but just
Lost connection to device.
Exited (sigterm)
the images reappear and disappear when scrolling up and down .
i have tried using image.network , cached network image , fadein image but not working . i have also limit my image request to 40 but also it crashes . image size are only 20-100 kb range .
// future function to load subcategory json
Future<subcategory> fetchallsubcategory() async {
final path = (await getApplicationDocumentsDirectory()).path;
final myDataResource = HttpNetworkResource(
url: serverurl +
"classes/subCategory?limit=40",
parser: (contents) => json.decode(contents),
headers: header,
cache: FileResource(File('$path/subcategoryall.json')),
maxAge: Duration(minutes: 10),
strategy: CacheStrategy.cacheFirst,
);
final myData = await myDataResource.get();
return subcategory.fromJson(myData);
}
//grid view
FutureBuilder(
future: fetchallsubcategory(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
return snapshot.hasData ? GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2),
itemCount: snapshot.data.results.length,
// padding: EdgeInsets.all(2.0),
// scrollDirection: Axis.horizontal,
itemBuilder: (context, int) {
return Card(
child:
CachedNetworkImage(imageUrl : snapshot.data.results[int].image),
);
}
) :CircularProgressIndicator();
},
)
I have created the same kind of app. I found NeverScrollableScrollPhysics() very helpful for scrollable image gridview. I hope the following code snippet helps you.
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Column(
children: <Widget>[
ConstrainedBox(
constraints: BoxConstraints(
minHeight: 10, // Set as you want or you can remove it also.
maxHeight: double.infinity,
),
child: Container(
child: GridView.count(
crossAxisCount:
MediaQuery.of(context).orientation == Orientation.portrait
? 3
: 4,
shrinkWrap: true,
scrollDirection: Axis.vertical,
physics: NeverScrollableScrollPhysics(),
childAspectRatio: .6,
children: thumbUrls
.map((urlThumb) => Card(
child: Container(
decoration: BoxDecoration(color: Colors.white),
child: GestureDetector(
onTap: () => Navigator.push(context,
new MaterialPageRoute(
builder: (context) {
return new FullScreenImagePage(wallpapers[urlThumb]);//Map wallpaper = {url_thumb : [id, url_image]}
})),
child: new Image.network(
urlThumb,
fit: BoxFit.cover,
),
)),
))
.toList(),
),
),
)
],
),
],
);
}
}
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(),
])
I show dialog with list inside it.
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text(select_conference),
content: ListView.separated(
itemCount: selected.length,
separatorBuilder: (context, index) => CommonDivider(),
itemBuilder: (context, index) => ListTile(...),
),
);
});
But no matter how many elements is has - dialog fills all available height. Is there any solution to solve this without calculating height of list elements?
Wrap your content with a Column and set mainAxisSize to MainAxisSize.min:
AlertDialog(
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
//your content
],
),
You can wrap it inside a SizedBox or ConstrainedBox
ConstrainedBox(
constraints: BoxConstraints(maxHeight: 100.0),
child: AlertDialog(
...
),
);
Alternatively, you can set shrinkWrap to true in your ListView so that it takes the least amount of vertical space necessary.
ListView(
shrinkWrap: true,
...
)
A Dialog's insetPadding property controls the padding around the dialog so you could set values to effectively reduce the height / width of the dialog, e.g.
showDialog(
context: context,
builder: (context) {
return AlertDialog(
insetPadding: EdgeInsets.symmetric(
horizontal: 50.0,
vertical: 100.0,
),
title: Text('...'),
content: Text('...'),
);
});