我想在占据屏幕剩余空间的屏幕点中显示 TabBar。这样做时,我的目标是在该
GridView
的两个选项卡中显示两个
TabBar
当我使用
Expanded
小部件时,它会导致应用程序崩溃,只有当我使用具有高度限制的 SizedBox
时,它才有效。
这是代码
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)
])
],
),
),
],
),
);
}
}
尝试以下操作,这是您的代码,但添加了您想要的内容。
要使
TabBar
分配屏幕的剩余空间,请使用 Expanded
小部件将其包裹起来。
此外,还有两个选项卡包含可滚动的网格布局:
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)
]),
)
],
),
),
],
),
),
);
}
第一个选项卡
第二个选项卡
注意:选项卡带有蓝色实线下划线,但它们的标签需要样式,请在您的主题中处理。