'How to use singlechildscroll view for Gridview.builder
I am using Singlechildscrollview on the top and column as first child. In Column i am using DefaultTabController and in Tabview i am using gridview.builder. Gridview builder can have any different number of products. How can give it dynamic height as TabBarView always needs fixed height
Code part:
import 'package:flutter/material.dart';
class TestScreen extends StatefulWidget {
const TestScreen({Key? key}) : super(key: key);
@override
State<TestScreen> createState() => _TestScreenState();
}
class _TestScreenState extends State<TestScreen> {
var indexSelected = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
bottomSheet: Container(
padding: const EdgeInsets.symmetric(horizontal: 0.0, vertical: 16.0),
child: ElevatedButton(
style: ElevatedButton.styleFrom(
padding:
const EdgeInsets.symmetric(horizontal: 25.0, vertical: 16.0),
primary: Theme.of(context).primaryColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25.0))),
onPressed: () {},
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
padding: const EdgeInsets.symmetric(
vertical: 2, horizontal: 8.0),
width: 24.0,
height: 24.0,
decoration: const BoxDecoration(
color: Colors.black,
shape: BoxShape.circle,
),
child: Text('fasdfa',
textAlign: TextAlign.center,
style: Theme.of(context)
.textTheme
.button!
.copyWith(color: Colors.white))),
const SizedBox(width: 8.0),
Text('USD 1000',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.button)
],
),
Text('NEXT',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.button)
]),
),
),
body: SafeArea(
child: SingleChildScrollView(
child: Column(
children: [
Padding(
/** header */
padding: const EdgeInsets.only(top: 14, bottom: 10),
child: Container(
height: 60,
padding: const EdgeInsets.symmetric(
horizontal: 15.0, vertical: 0.0),
width: MediaQuery.of(context).size.width * 1,
color: Colors.blue,
),
),
Container(
color: Colors.white,
width: MediaQuery.of(context).size.width,
child: Column(
children: [
const SizedBox(
width: 0,
height: 0,
),
Padding(
padding: const EdgeInsets.only(top: 4.0),
child: Column(
//_buildContent
children: [
Stack(
children: <Widget>[
Column(
children: <Widget>[
Container(
width:
MediaQuery.of(context).size.width * 1,
height: 200,
color: Colors.yellow,
),
],
),
Positioned(
top: MediaQuery.of(context).size.height * 0.265,
right: 20,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
shape: const CircleBorder(),
primary: Colors.white),
onPressed: () {},
child: Container(
color: Colors.blue,
width: 10,
height: MediaQuery.of(context).size.height *
0.055,
),
),
)
],
),
const Tabss(),
],
),
),
],
),
),
],
),
),
),
);
}
}
class Tabss extends StatefulWidget {
const Tabss({Key? key}) : super(key: key);
@override
_TabssState createState() => _TabssState();
}
class _TabssState extends State<Tabss> {
var indexSelected = 0;
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 25.0, vertical: 0.0),
color: Colors.red,
child: DefaultTabController(
length: 1,
child: Container(
color: Colors.white,
//primary: false,
child: Column(
children: [
TabBar(
onTap: (a) {
setState(() {});
},
labelStyle: Theme.of(context)
.textTheme
.button!
.copyWith(fontWeight: FontWeight.normal),
unselectedLabelStyle: Theme.of(context)
.textTheme
.subtitle1!
.copyWith(fontSize: 14),
isScrollable: true,
labelPadding:
const EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
indicatorWeight: 4,
indicatorColor: Colors.blue,
indicatorSize: TabBarIndicatorSize.label,
tabs: List.generate(
1,
(index) => const Text(
'TESTING',
style: TextStyle(
color: Colors.black,
),
),
),
),
Expanded(
child: TabBarView(
children: List.generate(
1,
(index) {
return GridView.builder(
shrinkWrap: true,
// FOR FOOD AND DECO
physics: const NeverScrollableScrollPhysics(),
itemCount: 30,
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
childAspectRatio: 0.95,
crossAxisSpacing: 15.0,
mainAxisSpacing: 10.0,
mainAxisExtent: 180,
crossAxisCount: 2),
itemBuilder: (BuildContext context, int index) {
return Container(
color: Colors.red,
alignment: Alignment.center,
child: Text(
index.toString(),
),
);
});
},
),
),
),
],
),
),
),
);
}
}
Solution 1:[1]
Hi Please try this-
Expanded(
child: GridView.builder(
primary: false,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: dataList.length,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
childAspectRatio: 0.95,
crossAxisSpacing: 15.0,
mainAxisSpacing: 10.0,
mainAxisExtent: 200,
crossAxisCount: 2),
)
Solution 2:[2]
If you want to wrap TabBarView with an Expanded to give it a fixed height, since you have nested Columns, you should wrap all TabBarView parents that are in a Column with an Expanded.
In this way you can leave GridView.builder scrollable! so you won't need SingleChildScrollView! your code will be something like:
import 'package:flutter/material.dart';
class TestScreen extends StatefulWidget {
const TestScreen({Key? key}) : super(key: key);
@override
State<TestScreen> createState() => _TestScreenState();
}
class _TestScreenState extends State<TestScreen> {
var indexSelected = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
bottomSheet: Container(
padding: const EdgeInsets.symmetric(horizontal: 0.0, vertical: 16.0),
child: ElevatedButton(
style: ElevatedButton.styleFrom(
padding:
const EdgeInsets.symmetric(horizontal: 25.0, vertical: 16.0),
primary: Theme.of(context).primaryColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25.0))),
onPressed: () {},
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
padding: const EdgeInsets.symmetric(
vertical: 2, horizontal: 8.0),
width: 24.0,
height: 24.0,
decoration: const BoxDecoration(
color: Colors.black,
shape: BoxShape.circle,
),
child: Text('fasdfa',
textAlign: TextAlign.center,
style: Theme.of(context)
.textTheme
.button!
.copyWith(color: Colors.white))),
const SizedBox(width: 8.0),
Text('USD 1000',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.button)
],
),
Text('NEXT',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.button)
]),
),
),
body: SafeArea(
child: Column(
children: [
Padding(
/** header */
padding: const EdgeInsets.only(top: 14, bottom: 10),
child: Container(
height: 60,
padding:
const EdgeInsets.symmetric(horizontal: 15.0, vertical: 0.0),
width: MediaQuery.of(context).size.width * 1,
color: Colors.blue,
),
),
Expanded(
child: Container(
color: Colors.white,
width: MediaQuery.of(context).size.width,
child: Padding(
padding: const EdgeInsets.only(top: 4.0),
child: Column(
//_buildContent
children: [
Stack(
children: <Widget>[
Column(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width * 1,
height: 200,
color: Colors.yellow,
),
],
),
Positioned(
top: MediaQuery.of(context).size.height * 0.265,
right: 20,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
shape: const CircleBorder(),
primary: Colors.white),
onPressed: () {},
child: Container(
color: Colors.blue,
width: 10,
height:
MediaQuery.of(context).size.height * 0.055,
),
),
)
],
),
const Expanded(child: Tabss()),
],
),
),
),
),
],
),
),
);
}
}
class Tabss extends StatefulWidget {
const Tabss({Key? key}) : super(key: key);
@override
_TabssState createState() => _TabssState();
}
class _TabssState extends State<Tabss> {
var indexSelected = 0;
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 25.0, vertical: 0.0),
color: Colors.red,
child: DefaultTabController(
length: 3,
child: Container(
color: Colors.white,
//primary: false,
child: Column(
children: [
TabBar(
onTap: (a) {
setState(() {});
},
labelStyle: Theme.of(context)
.textTheme
.button!
.copyWith(fontWeight: FontWeight.normal),
unselectedLabelStyle: Theme.of(context)
.textTheme
.subtitle1!
.copyWith(fontSize: 14),
isScrollable: true,
labelPadding:
const EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
indicatorWeight: 4,
indicatorColor: Colors.blue,
indicatorSize: TabBarIndicatorSize.label,
tabs: List.generate(
3,
(index) => const Text(
'TESTING',
style: TextStyle(
color: Colors.black,
),
),
),
),
Expanded(
child: TabBarView(
children: List.generate(
3,
(index) {
return GridView.builder(
shrinkWrap: true,
// FOR FOOD AND DECO
itemCount: 30,
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
childAspectRatio: 0.95,
crossAxisSpacing: 15.0,
mainAxisSpacing: 10.0,
mainAxisExtent: 180,
crossAxisCount: 2),
itemBuilder: (BuildContext context, int index) {
return Container(
color: Colors.red,
alignment: Alignment.center,
child: Text(
index.toString(),
),
);
},
);
},
),
),
),
],
),
),
),
);
}
}
Solution 3:[3]
You will try this..
class TestScreen extends StatefulWidget {
const TestScreen({Key? key}) : super(key: key);
@override
State<TestScreen> createState() => _TestScreenState();
}
class _TestScreenState extends State<TestScreen> {
var indexSelected = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
bottomSheet: ElevatedButton(
style: ElevatedButton.styleFrom(
padding:
const EdgeInsets.symmetric(horizontal: 25.0, vertical: 16.0),
primary: Theme.of(context).primaryColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25.0))),
onPressed: () {},
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
padding: const EdgeInsets.symmetric(
vertical: 2, horizontal: 8.0),
width: 24.0,
height: 24.0,
decoration: const BoxDecoration(
color: Colors.black,
shape: BoxShape.circle,
),
child: Text('fasdfa',
textAlign: TextAlign.center,
style: Theme.of(context)
.textTheme
.button!
.copyWith(color: Colors.white))),
const SizedBox(width: 8.0),
Text('USD 1000',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.button)
],
),
Text('NEXT',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.button)
]),
),
body: SafeArea(
child: Column(
children: [
Padding(
/** header */
padding: const EdgeInsets.only(top: 14, bottom: 10),
child: Container(
height: 60,
padding:
const EdgeInsets.symmetric(horizontal: 15.0, vertical: 0.0),
width: MediaQuery.of(context).size.width * 1,
color: Colors.blue,
),
),
Expanded(
child: Container(
color: Colors.white,
width: MediaQuery.of(context).size.width,
child: Padding(
padding: const EdgeInsets.only(top: 4.0),
child: Column(
//_buildContent
children: [
Stack(
children: <Widget>[
Column(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width * 1,
height: 200,
color: Colors.yellow,
),
],
),
Positioned(
top: MediaQuery.of(context).size.height * 0.265,
right: 20,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
shape: const CircleBorder(),
primary: Colors.white),
onPressed: () {},
child: Container(
color: Colors.blue,
width: 10,
height:
MediaQuery.of(context).size.height * 0.055,
),
),
)
],
),
const Expanded(child: Tabss()),
],
),
),
),
),
],
),
),
);
}
}
class Tabss extends StatefulWidget {
const Tabss({Key? key}) : super(key: key);
@override
_TabssState createState() => _TabssState();
}
class _TabssState extends State<Tabss> {
var indexSelected = 0;
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 3,
child: Column(
children: [
TabBar(
onTap: (a) {
setState(() {});
},
labelStyle: Theme.of(context)
.textTheme
.button!
.copyWith(fontWeight: FontWeight.normal),
unselectedLabelStyle: Theme.of(context)
.textTheme
.subtitle1!
.copyWith(fontSize: 14),
isScrollable: true,
labelPadding:
const EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
indicatorWeight: 4,
indicatorColor: Colors.blue,
indicatorSize: TabBarIndicatorSize.label,
tabs: List.generate(
3,
(index) => const Text(
'TESTING',
style: TextStyle(
color: Colors.black,
),
),
),
),
Flexible(
flex: 6,
child: TabBarView(
children: List.generate(
3,
(index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: GridView.builder(
shrinkWrap: true,
// FOR FOOD AND DECO
itemCount: 30,
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
childAspectRatio: 0.95,
crossAxisSpacing: 15.0,
mainAxisSpacing: 10.0,
mainAxisExtent: 180,
crossAxisCount: 2),
itemBuilder: (BuildContext context, int index) {
return Container(
color: Colors.red,
alignment: Alignment.center,
child: Text(
index.toString(),
),
);
},
),
);
},
),
),
),
const Spacer(),
],
),
);
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Vishal_VE |
| Solution 2 | |
| Solution 3 |
