I need to implement a tab bar in following formation:
- AppBar
- DropDown
- TabBar
- Slider
- TabBarView
Problem is: I'm putting everything from dropdown to tab bar view inside a column which goes inside a SingleChildScrollView
. Which does not work.
My code:
late TabController _tabController;
@override
void initState() {
super.initState();
_merchantProducts = _getMerchantData();
_tabController = TabController(length: 2, vsync: this);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
...app bar
),
body: SingleChildScrollView(
child: _buildItems(context),
),
);
}
Widget _buildItems(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 15),
Container(
padding: EdgeInsets.only(left: 10, right: 20),
child: AddressDropDown(),
),
SizedBox(
height: 20,
),
TabBar(
controller: _tabController,
indicatorColor: CustomColors.primary,
labelColor: CustomColors.primary,
unselectedLabelColor: CustomColors.grey,
isScrollable: true,
tabs: [
Tab(
text: 'All',
),
Tab(
text: 'Popular',
),
],
),
Center(
child: AdSliderCard(),
),
SizedBox(
height: 20,
),
TabBarView(
controller: _tabController,
children: [
_buildMerchantProductList(context),
_buildMerchantProductList(context),
],
),
],
);
}
Widget _buildMerchantProductList(BuildContext context) {
return ListContainer(
data: _merchantProducts,
isHorizontal: false,
isScrollable: true,
);
}
}
How to solve the issue?
UPDATE: I can make the TabBarView scrollable without an issue. I need to make the entire page scrollable.
CodePudding user response:
Use your SingleChildScrollView
inside TabBarView
and wrap TabBarView
with Expanded
widget.
class _TXSState extends State<TXS> with SingleTickerProviderStateMixin {
String dropdownValue = 'One';
late TabController _tabController;
@override
void initState() {
super.initState();
_tabController = TabController(length: 2, vsync: this);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
children: [
DropdownButton<String>(
value: dropdownValue,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: const TextStyle(color: Colors.deepPurple),
underline: Container(
height: 2,
color: Colors.deepPurpleAccent,
),
onChanged: (String? newValue) {
setState(() {
dropdownValue = newValue!;
});
},
items: <String>['One', 'Two', 'Free', 'Four']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
TabBar(
controller: _tabController,
isScrollable: true,
tabs: [
Tab(
text: 'All',
),
Tab(
text: 'Popular',
),
],
),
Slider(value: .3, onChanged: (v) {}),
Expanded(
child: TabBarView(
controller: _tabController,
children: [
Text("A"),
SingleChildScrollView(
child: Column(
children: [
...List.generate(
33,
(index) => Text(
index.toString(),
),
)
],
)),
],
),
),
],
),
);
}
}
CodePudding user response:
In your builditems, better way to achieve what you need is to use CustomScrollView:
CustomScrollView(
slivers: [
SliverToBoxAdapter(
child: SizedBox(height: 15),
),
SliverToBoxAdapter(
child: Container(
padding: EdgeInsets.only(left: 10, right: 20),
child: AddressDropDown(),
),
),
SliverToBoxAdapter(
child: SizedBox(height: 20),
),
SliverToBoxAdapter(
child: Container(
height: 50,
child: TabBar(
controller: _tabController,
indicatorColor: CustomColors.primary,
labelColor: CustomColors.primary,
unselectedLabelColor: CustomColors.grey,
isScrollable: true,
tabs: [
Tab(
text: 'All',
),
Tab(
text: 'Popular',
),
],
),
),
),
SliverToBoxAdapter(
child: Container(
height: 200,
child: Center(
child: AdSliderCard(),
),
),
),
SliverToBoxAdapter(
child: SizedBox(height: 20),
),
SliverFillRemaining(
child: TabBarView(
controller: _tabController,
children: [
_buildMerchantProductList(context),
_buildMerchantProductList(context),
],
),
),
],
)