I want to display TabBar in a screen point in which it take the remaining space of the screen. While doing that, I aim to display two GridView
s in a two tabs of that TabBar
When I use an Expanded
Widget it causes the app the crash, it only works if I use a SizedBox
with height constraints.
Here is the code
import 'package:bespoked_1_1/utils/constants.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
class SellersHomePage extends StatefulWidget {
const SellersHomePage({super.key});
@override
State<SellersHomePage> createState() => _SellersHomePageState();
}
class _SellersHomePageState extends State<SellersHomePage> {
@override
Widget build(BuildContext context) {
final screenWidth = MediaQuery.of(context).size.width;
final screenHeight = MediaQuery.of(context).size.height;
return Scaffold(
appBar: AppBar(
title: Text('Epoxy Forever'),
centerTitle: true,
actions: [
IconButton(
onPressed: () {},
icon: Icon(
Icons.ios_share,
),
),
IconButton(
onPressed: () {},
icon: Icon(
Icons.shopping_cart_outlined,
),
),
],
),
body: Column(
mainAxisSize: MainAxisSize.min,
children: [
Stack(
children: [
SizedBox(
height: screenHeight * 0.3,
width: screenWidth,
child: ShaderMask(
shaderCallback: (rect) {
return LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: const [Colors.black, Colors.transparent],
).createShader(
Rect.fromLTRB(0, 0, rect.width, rect.height));
},
blendMode: BlendMode.dstIn,
child: Image(
fit: BoxFit
.cover, //TODO: Give the option to change the fit of the image
height: screenHeight * 0.2,
image: NetworkImage(
'https://img.freepik.com/free-photo/carpenter-cutting-mdf-board-inside-workshop_23-2149451051.jpg'),
),
),
),
//sellers logo and details
Positioned(
top: 20,
left: 0,
right: 0,
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
children: const [
//profile image
CircleAvatar(
radius: 50,
backgroundImage: NetworkImage(
'https://t3.ftcdn.net/jpg/01/37/76/72/360_F_137767250_pocwIHgKu5rDuYFDNCTNcPy77gHb1lfh.jpg'),
),
//name
Text(
'Karls Carpentry',
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 24),
),
//sub heading
Text(
'Specialist in Fine custom furniture and upholstery',
style: TextStyle(fontSize: 16),
textAlign: TextAlign.center,
),
],
),
),
),
],
),
//business stats
Center(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 30),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25), color: Colors.grey),
padding: EdgeInsets.symmetric(horizontal: 30, vertical: 10),
child: const Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
//avg rating
Column(
children: [
Text(
'4.8',
style: TextStyle(fontSize: 24),
),
Text('Avg Rating')
],
),
//followers
Column(
children: [
Text(
'28',
style: TextStyle(fontSize: 24),
),
Text('Avg Rating')
],
),
//callouts and items sold
Column(
children: [
Text(
'200',
style: TextStyle(fontSize: 24),
),
Text('Avg Rating')
],
)
],
),
),
),
DefaultTabController(
length: 3,
child: Column(
children: [
//tabs
TabBar(indicatorSize: TabBarIndicatorSize.tab, tabs: [
Tab(
text: 'Shop',
),
Tab(
text: 'Posts',
),
Tab(
text: 'About',
),
]),
//tabviews
TabBarView(children: [
Icon(Icons.shop),
Icon(Icons.image),
Icon(Icons.info)
])
],
),
),
],
),
);
}
}
Try the following, it's your code but added what you want.
To make the TabBar
allocate the remaining space of the screen, wrap it with Expanded
widget.
Also, there are two tabs with that hold a scrollable Grid layout:
class SellersHomePage extends StatefulWidget {
const SellersHomePage({super.key});
@override
State<SellersHomePage> createState() => _SellersHomePageState();
}
class _SellersHomePageState extends State<SellersHomePage> {
@override
Widget build(BuildContext context) {
final screenWidth = MediaQuery.of(context).size.width;
final screenHeight = MediaQuery.of(context).size.height;
return DefaultTabController(
length: 3,
child: Scaffold(
appBar: AppBar(
title: Text('Epoxy Forever'),
centerTitle: true,
actions: [
IconButton(
onPressed: () {},
icon: Icon(
Icons.ios_share,
),
),
IconButton(
onPressed: () {},
icon: Icon(
Icons.shopping_cart_outlined,
),
),
],
),
body: Column(
mainAxisSize: MainAxisSize.min,
children: [
Stack(
children: [
SizedBox(
height: screenHeight * 0.3,
width: screenWidth,
child: ShaderMask(
shaderCallback: (rect) {
return LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: const [Colors.black, Colors.transparent],
).createShader(
Rect.fromLTRB(0, 0, rect.width, rect.height));
},
blendMode: BlendMode.dstIn,
child: Image(
fit: BoxFit
.cover, //TODO: Give the option to change the fit of the image
height: screenHeight * 0.2,
image: NetworkImage(
'https://img.freepik.com/free-photo/carpenter-cutting-mdf-board-inside-workshop_23-2149451051.jpg'),
),
),
),
//sellers logo and details
Positioned(
top: 20,
left: 0,
right: 0,
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
children: const [
//profile image
CircleAvatar(
radius: 50,
backgroundImage: NetworkImage(
'https://t3.ftcdn.net/jpg/01/37/76/72/360_F_137767250_pocwIHgKu5rDuYFDNCTNcPy77gHb1lfh.jpg'),
),
//name
Text(
'Karls Carpentry',
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 24),
),
//sub heading
Text(
'Specialist in Fine custom furniture and upholstery',
style: TextStyle(fontSize: 16),
textAlign: TextAlign.center,
),
],
),
),
),
],
),
//business stats
Center(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 30),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25), color: Colors.grey),
padding: EdgeInsets.symmetric(horizontal: 30, vertical: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
//avg rating
Column(
children: [
Text(
'4.8',
style: TextStyle(fontSize: 24),
),
Text('Avg Rating')
],
),
//followers
Column(
children: [
Text(
'28',
style: TextStyle(fontSize: 24),
),
Text('Avg Rating')
],
),
//callouts and items sold
Column(
children: [
Text(
'200',
style: TextStyle(fontSize: 24),
),
Text('Avg Rating')
],
)
],
),
),
),
Expanded(
child: Column(
children: [
//tabs
TabBar(indicatorSize: TabBarIndicatorSize.tab, tabs: [
Tab(
text: 'Shop',
),
Tab(
text: 'Posts',
),
Tab(
text: 'About',
),
]),
//tabviews
Expanded(
child: TabBarView(children: [
GridView.builder(
itemBuilder: (context,index)=>Container(color: Colors.yellow),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
),
),
GridView.builder(
itemBuilder: (context,index)=>Container(color: Colors.purple),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
),
),
Icon(Icons.info)
]),
)
],
),
),
],
),
),
);
}
First Tab
Second Tab
Note: Tabs are underlined with the blue solid line, but their labels needs styling, handle it in your theme.