How to nest tab in flutter? - flutter

How to nest tab view as a child of column in flutter?
I don't want to add tabs as a child of app bar bottom cause my tabs are not on top. It is somewhere in the body.
So I tried the above method & also I tried wrapping it inside a nested scaffold. Both of them seems not working.
Following is what I've tried.
body: SingleChildScrollView(
physics: BouncingScrollPhysics(),
child: Container(
child: Column(children: [
Container(
padding: EdgeInsets.all(10),
child: TextInput(
placeholder: 'Search',
leadingIcon: searchIcon,
),
),
DefaultTabController(
length: 3,
child: Column(
children: [
TabBar(
tabs: [
Tab(icon: Icon(Icons.directions_car)),
Tab(icon: Icon(Icons.directions_transit)),
Tab(icon: Icon(Icons.directions_bike)),
],
),
TabBarView(
children: [
Icon(Icons.directions_car),
Icon(Icons.directions_transit),
Icon(Icons.directions_bike),
],
),
],
),
),

give a height to tabcontroller and then wrap tabbarview with expanded.
body: SingleChildScrollView(
physics: BouncingScrollPhysics(),
child: Container(
child: Column(children: [
Container(
height:10,
padding: EdgeInsets.all(10),
),
Container(
height:100,//add height as per your need
child:DefaultTabController(
length: 3,
child: Column(
children: [
TabBar(
tabs: [
Tab(icon: Icon(Icons.directions_car)),
Tab(icon: Icon(Icons.directions_transit)),
Tab(icon: Icon(Icons.directions_bike)),
],
),
Expanded(
child:TabBarView(
children: [
Icon(Icons.directions_car),
Icon(Icons.directions_transit),
Icon(Icons.directions_bike),
],
),
),
],
),
),
),
])))

Related

TabBar height expaned to rest of the screen

On one page I have DropDownSearch, SizedBox, TextButton and Tabs. Everything works fine but I have problem to set TabBarView height to be flexible to the bottom of the screen. I tried Flexible, Expanded (error: RenderFlex children have non-zero flex but incoming height constraints are unbounded) and Container/SizedBox with height: MediaQuery.of(context).size.height (error: A RenderFlex overflowed by 225 pixels on the bottom).
Any idea how to set the height of Container to fill rest of the screen? Or use different widget?
Thanks!
body: Column(
children: [
DropdownSearch<String>( ... )
const SizedBox(
width: 10,
),
TextButton(
onPressed: () {
setState(() {
});
},
child: Text('Click me',),
),
DefaultTabController(
length: 3,
child: Column(
children: [
Container(
child: TabBar(
tabs: [
Tab(icon: Icon(Icons.directions_car)),
Tab(icon: Icon(Icons.directions_transit)),
Tab(icon: Icon(Icons.directions_bike)),
],
),
),
SizedBox(
height: MediaQuery.of(context).size.height,
child: TabBarView(
children: [
Icon(Icons.directions_car),
Icon(Icons.directions_transit),
Icon(Icons.directions_bike),
],
),
),
],
),
),
Instead of giving TabBarView screen height, wrap it with Expanded to get height as much as possible. ,try this:
Column(
children: [
SizedBox(
width: 10,
),
TextButton(
onPressed: () {
setState(() {});
},
child: Text(
'Click me',
),
),
Expanded( // <--- add this
child: DefaultTabController(
length: 3,
child: Column(
children: [
Container(
child: TabBar(
tabs: [
Tab(icon: Icon(Icons.directions_car)),
Tab(icon: Icon(Icons.directions_transit)),
Tab(
icon: Icon(
Icons.directions_bike,
)),
],
),
),
Expanded(// <--- add this
child: TabBarView(
children: [
Icon(Icons.directions_car),
Icon(Icons.directions_transit),
Icon(Icons.directions_bike),
],
),
),
],
),
),
)
],
)
Wrap with Expanded widget to get available space. If you set full height on TabBarView there will be no space left for parent widget.
body: Column(children: [
// DropdownSearch<String>( ... )
const SizedBox(
width: 10,
),
TextButton(
onPressed: () {
setState(() {});
},
child: Text(
'Click me',
),
),
Expanded( //this one
child: DefaultTabController(
length: 3,
child: Column(
children: [
Container(
child: TabBar(
tabs: [
Tab(icon: Icon(Icons.directions_car)),
Tab(icon: Icon(Icons.directions_transit)),
Tab(icon: Icon(Icons.directions_bike)),
],
),
),
Expanded( //this one
// height: MediaQuery.of(context).size.height,
child: TabBarView(
children: [
Icon(Icons.directions_car),
Icon(Icons.directions_transit),
Icon(Icons.directions_bike),
],
),
),
],
),
),
),
]));

flutter tab bar view inside scroll able column

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.
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),
],
),
),
],
)
Use CustomScrollView and SliverFillRemaining for TabBarView.
return Scaffold(
body: CustomScrollView(
slivers: [
const SliverAppBar(
title: Text("A"),
),
SliverList(
delegate: SliverChildListDelegate.fixed(
[
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: const [
Tab(
text: 'All',
),
Tab(
text: 'Popular',
),
],
),
Slider(value: .3, onChanged: (v) {}),
],
),
),
SliverFillViewport(
delegate: SliverChildListDelegate.fixed([
TabBarView(
physics: const NeverScrollableScrollPhysics(),
//*
controller: _tabController,
children: [
SingleChildScrollView(
physics: const NeverScrollableScrollPhysics(),
child: Column(
children: [
...List.generate(
33,
(index) => Text(
"tab A: $index",
),
)
],
),
),
SingleChildScrollView(
physics: const NeverScrollableScrollPhysics(),
child: Column(
children: [
...List.generate(
33,
(index) => Text(
"tab B: $index",
),
)
],
),
)
],
),
]),
)
],
),
);

Force flutter's TabBarView to fit to its content

How can I force TabBarView to take min height possible to fit its content?
import 'package:flutter/material.dart';
void main() {
runApp(TabBarDemo());
}
class TabBarDemo extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: DefaultTabController(
length: 3,
child: Scaffold(
appBar: AppBar(
bottom: TabBar(
tabs: [
Tab(icon: Icon(Icons.directions_car)),
Tab(icon: Icon(Icons.directions_transit)),
Tab(icon: Icon(Icons.directions_bike)),
],
),
title: Text('Tabs Demo'),
),
body: Column(children: [
Text('Header Widget'),
Expanded(
child: TabBarView(
children: [
Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.directions_car),
Icon(Icons.directions_car),
],
),
Icon(Icons.directions_transit),
Icon(Icons.directions_bike),
],
),
),
Text('Footer Widget')
]),
),
),
);
}
}
Use BoxConstraint to restrict the height of TabBarView
Column(children: [
Text('Header Widget'),
Container(
constraints: BoxConstraints(
maxHeight: 100.0,
),
child: TabBarView(
children: [
Container(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.directions_car),
Icon(Icons.directions_car),
],
),
),
Icon(Icons.directions_transit),
Icon(Icons.directions_bike),
],
),
),
Text('Footer Widget')
]),
Output:
Refer Blog:
https://medium.com/flutterworld/flutter-how-to-set-the-minimum-height-to-widget-36967b310ffe

How to make a container with tabview & listview occupy space upto bottom

I have implemented tab layout which consists of two tabs, each tab view has a listview, container with tabview & listview should occupy space upto bottom as of now i place static value of 400, so only up to 400 the listview appears, i need the list view to be appeared up to bottom. can you please me to fix this
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(left:20.0,right:20.0),
child: Container(
color: Colors.white,
child: new TabBar(
controller: _controller,
labelColor: Colors.deepOrange,
tabs: [
new Tab(
icon: const Icon(Icons.description),
text: 'ABC',
),
new Tab(
icon: const Icon(Icons.assignment),
text: 'XYZ',
),
],
),
),
),
Padding(
padding: const EdgeInsets.only(left:20.0,right:20.0),
child: Container(
color: Colors.white,
height: 400.0,
child: new TabBarView(
controller: _controller,
children: <Widget>[
ListView(
children: <Widget>[
ListTile(
title: Text('Sun'),
),
ListTile(
title: Text('Moon'),
),
ListTile(
title: Text('Star'),
),
],
),
ListView(
children: <Widget>[
ListTile(
title: Text('Sun'),
),
ListTile(
title: Text('Moon'),
),
ListTile(
title: Text('Star'),
),
],
),
],
),
),
),
],
),
);
}
I have Used Expanded & Flex Widgets which solved the problem
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.only(left:20.0,right:20.0),
child: Container(
color: Colors.white,
child: new TabBar(
controller: _controller,
labelColor: Colors.deepOrange,
tabs: [
new Tab(
icon: const Icon(Icons.description),
text: 'Current Openings',
),
new Tab(
icon: const Icon(Icons.assignment),
text: 'Applied Jobs',
),
],
),
),
),
flex: 1,
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(left:20.0,right:20.0,bottom: 10.0),
child: Container(
color: Colors.white,
child: new TabBarView(
controller: _controller,
children: <Widget>[
ListView(
children: <Widget>[
ListTile(
title: Text('Sun'),
),
],
),
ListView(
children: <Widget>[
ListTile(
title: Text('Sun'),
),
],
),
],
),
),
),
flex: 9,
),
],
),
);
}

Is it possible to have Tab Bar with content before in Flutter?

I just wanted to ask, if it is possible to have Tab Bar View in Flutter with content before tabs (I mean that the Tabs are for example in the middle of the screen and they have content before - e.g. profile information - like Instagram and its profile section).
Example of what I mean here
I have already tried the default Tab View, but it is not what I want.
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
flexibleSpace: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TabBar(
labelColor: Colors.teal,
labelStyle: TextStyle(
fontWeight: FontWeight.bold,
),
unselectedLabelColor: Colors.black45,
unselectedLabelStyle: TextStyle(
fontWeight: FontWeight.normal
),
tabs: [
Tab(
icon: Icon(Icons.list)
),
Tab(
icon: Icon(Icons.map)
)
],
),
],
),
),
body: TabBarView(
children: <Widget>[
Container(
child: ListView(
children: <Widget>[
Container(
color: Colors.red,
height: 100,
child: Text('Hello'),
),
],
)
),
Container(
child: Text('testuju'),
)
],
),
),
);
Is it even possible to do it with Tab View, or should I fake tabs with styled buttons? Thanks a lot!
You can do it like this
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: PreferredSize(
child: AppBar(
backgroundColor: Colors.greenAccent,
bottom: TabBar(
controller: tabController,
tabs: [
Tab(
child: Text("Login"),
),
Tab(
child: Text("Sign Up"),
),
],
indicatorColor: Colors.black,
),
flexibleSpace: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Colors.red,
Colors.orange,
],
),
),
),
),
preferredSize: Size.fromHeight(200.0),
),
body: TabBarView(
controller: tabController,
children: [
LoginApp(),
SignUpApp(),
],
),
),
);
you can try that:
Scaffold(
body: DefaultTabController(
initialIndex: // initial tab,
length: // tabs numbers,
child: NestedScrollView(
headerSliverBuilder: (buildContext, isScrolled){
return <Widget>[
SliverAppBar(
floating: false,
pinned: true,
primary: true,
automaticallyImplyLeading: false,
actions: <Widget>[
BackBtnIcon(action: (){
Navigator.pop(context);
},
),
SizedBox(width: 6,),
],
title: Text(memberFullName),
),
SliverPadding(
padding: EdgeInsets.all(0),
sliver: SliverList(
delegate: SliverChildListDelegate(
[
Container(
color: CopticColors.mainButtonColor,
child: CustomTabBar()
),
]
)
),
)
];
},
body: SafeArea(
minimum: EdgeInsets.all(20),
child: TabBarView(
// physics: new NeverScrollableScrollPhysics(),
children: [ // replace with your tabs
ConfessionTab(model: snapshot.data,),
CommunicationDetails(model: snapshot.data,),
GeneralDetails(model: snapshot.data,),
ChurchDetails(model: snapshot.data,),
GovDetails(model: snapshot.data,),
],
)
)
),
);