How to implement ExpansionPanelList with listview builder flutter? - flutter

I want to implement listview builder inside ExpansionPanelList. Under each expansion tile it will have tabbar and tabbarview. Inside the tabbarview it will display listview. I have tried to implemented but the view is not rendering properly. Throwing error
RenderBox was not laid out: RenderRepaintBoundary#92515 NEEDS-LAYOUT NEEDS-PAINT
'package:flutter/src/rendering/box.dart':
Failed assertion: line 1930 pos 12: 'hasSize'
My Implemented code:
List<bool> _isOpen =[true, false]
ExpansionPanelList(
children: [
ExpansionPanel(
isExpanded: _isOpen[0],
headerBuilder: (context, isOpen){
return Text("Activities");
},
body: Column(
children: [
Container(child: tabView()),
Flexible(child: tabBarView()),
],
),),
ExpansionPanel(
isExpanded: _isOpen[1],
headerBuilder: (context, isOpen){
return Text("Ports");
},
body: Text("Test"),)
],
expansionCallback: (i, isOpen) {
setState(() {
_isOpen[i] =!isOpen;
});
},
),
tabview widget
Widget tabView(){
return PreferredSize(
preferredSize: Size.fromHeight(70),
child: Align(
alignment: Alignment.centerLeft,
child: Container(
width: MediaQuery.of(context).size.width ,
child: TabBar(
isScrollable: true,
labelPadding: EdgeInsets.symmetric(horizontal: 8),
controller: _tabController,
unselectedLabelColor: CustomColors.Black,
indicatorSize: TabBarIndicatorSize.label,
indicator: BoxDecoration(
borderRadius: BorderRadius.circular(50),
color: CustomColors.oldLace),
tabs: tabNames),
),
));
}
tabbarView
Widget tabBarView(){
return TabBarView(controller: _tabController,
children: [
listItems(),
Center(child: Text("Favorite list will be shown here")),
Center(child: Text("Filter")),
],);
}

Wrap your ExpansionPanelList in SingleChildScrollView and Give fix height to your TabBarView by Wraping Inside Container.
Full Code Snippet below
import 'package:flutter/material.dart';
class Expand extends StatefulWidget {
const Expand({Key? key}) : super(key: key);
#override
_ExpandState createState() => _ExpandState();
}
class _ExpandState extends State<Expand> with SingleTickerProviderStateMixin {
List<bool> _isOpen = [false, false];
late TabController _tabController;
static const List<Tab> myTabs = <Tab>[
Tab(text: 'LEFT'),
Tab(text: 'RIGHT'),
];
#override
void initState() {
super.initState();
_tabController = TabController(vsync: this, length: myTabs.length);
}
#override
void dispose() {
_tabController.dispose();
super.dispose();
}
Widget tabView() {
return PreferredSize(
preferredSize: Size.fromHeight(70),
child: Align(
alignment: Alignment.centerLeft,
child: Container(
width: MediaQuery.of(context).size.width,
// height: 200,
child: TabBar(
isScrollable: true,
labelPadding: EdgeInsets.symmetric(horizontal: 8),
controller: _tabController,
unselectedLabelColor: Colors.black,
indicatorSize: TabBarIndicatorSize.label,
indicator: BoxDecoration(
borderRadius: BorderRadius.circular(50),
// color: CustomColors.oldLace
),
tabs: myTabs,
// tabs: tabNames
),
),
));
}
Widget tabBarView() {
return Container(
height: 400,
width: 400,
child: TabBarView(
controller: _tabController,
children: [
// listItems(),
Center(child: Text("Favorite list will be shown here")),
Center(child: Text("Filter")),
],
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
// height: 400,
// width: 500,
child: ExpansionPanelList(
children: [
ExpansionPanel(
isExpanded: _isOpen[0],
headerBuilder: (context, isOpen) {
return Text("Activities");
},
body: Column(
mainAxisSize: MainAxisSize.min,
children: [
tabView(),
tabBarView(),
],
),
),
ExpansionPanel(
isExpanded: _isOpen[1],
headerBuilder: (context, isOpen) {
return Text("Ports");
},
body: Text("Test"),
)
],
expansionCallback: (i, isOpen) {
setState(() {
_isOpen[i] = !isOpen;
});
},
),
),
);
}
}

import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Expansion Panel List',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
TabController _tabController;
#override
void initState() {
_tabController = TabController(length: 2, vsync: this);
super.initState();
}
#override
void dispose() {
_tabController.dispose();
super.dispose();
}
List<bool> _isOpen = [true, false];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Draggable Test'),
),
body: Column(
mainAxisSize: MainAxisSize.min,
children: [
ExpansionPanelList(
children: [
ExpansionPanel(
isExpanded: _isOpen[0],
headerBuilder: (context, isOpen) {
return Text("Activities");
},
body: Column(
children: [
Container(child: tabView()),
tabBarView(),
],
)),
ExpansionPanel(
isExpanded: _isOpen[1],
headerBuilder: (context, isOpen) {
return Text("Ports");
},
body: Column(
children: [
Container(child: tabView()),
tabBarView(),
],
))
],
expansionCallback: (i, isOpen) {
setState(() {
_isOpen[i] = !isOpen;
});
},
),
],
));
}
Widget tabView() {
return PreferredSize(
preferredSize: Size.fromHeight(70),
child: Align(
alignment: Alignment.centerLeft,
child: Container(
width: MediaQuery.of(context).size.width,
child: TabBar(
isScrollable: true,
labelPadding: EdgeInsets.symmetric(horizontal: 8),
controller: _tabController,
unselectedLabelColor: Colors.blue,
indicatorSize: TabBarIndicatorSize.label,
indicator: BoxDecoration(borderRadius: BorderRadius.circular(50), color: Colors.black),
tabs: [
Tab(text: 'Activities'),
Tab(text: 'Ports'),
],
),
),
));
}
Widget tabBarView() {
return Container(
height: 100,
child: TabBarView(
controller: _tabController,
children: [
// listItems(),
Center(child: Text("Favorite list will be shown here")),
Center(child: Text("Filter")),
],
),
);
}
}

Related

Scroll ListView inside PageView from SingleChildScrollView in Flutter

I have a tab bar with a PageView inside each TabBarView. Each PageView has a ListView and when I scroll it, how can I scroll from the Scaffold's SingleChildScrollView rather than just scrolling the ListView inside the TabBarView?
Currently, the tab bar stays on the same position when I scroll the TabBarView, which looks terrible. How can I scroll individual TabBarView from SingleChildScrollView?
I tried tweaking with physics, but didn't turn out the way I wanted it to.
IMAGE :
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
int currIndex = 0;
TabController _tabController;
#override
void initState() {
super.initState();
_tabController =
TabController(vsync: this, length: 3, initialIndex: currIndex);
_tabController.addListener(() {
_handleTabSelection();
});
}
void _handleTabSelection() {
setState(() {
currIndex = _tabController.index == null ? 0 : _tabController.index;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: DefaultTabController(
length: 3,
initialIndex: 0,
child: SingleChildScrollView(
child: Container(
height: MediaQuery.of(context).size.height,
child: Column(
children: [
Container(
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8),
child: Container(
child: Text(
"HOME",
style: TextStyle(fontSize: 25),
)),
),
_buildTabBar(context),
],
),
),
Expanded(
child: _buildTabBarView(
context,
),
)
],
),
),
),
),
),
);
}
TabBarView _buildTabBarView(BuildContext context) {
return TabBarView(
controller: _tabController,
children: List.generate(
3,
(index) => Container(
color: Colors.red,
child: ListView.builder(
itemCount: 50,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 60,
color: Colors.blue,
child: Center(child: Text("$index"))),
);
},
),
)));
}
Widget _buildTabBar(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8),
child: Container(
height: 45,
width: double.infinity,
decoration: buildTabBarStyle(),
child: TabBar(
controller: _tabController,
isScrollable: false,
tabs: List.generate(
3,
(index) => Center(
child: Text(
"$index",
style: TextStyle(color: Colors.black),
),
)),
),
),
);
}
BoxDecoration buildTabBarStyle() {
return BoxDecoration(
color: Color.fromARGB(255, 230, 248, 255),
border: Border.all(
width: 1,
color: Colors.black,
),
borderRadius: BorderRadius.all(Radius.circular(10)),
);
}
}
Here is a different approach to do it simply.
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
late final TabController controller;
#override
void initState() {
super.initState();
controller = TabController(length: 3, vsync: this);
}
BoxDecoration buildTabBarStyle() {
return BoxDecoration(
color: Color.fromARGB(255, 230, 248, 255),
border: Border.all(
width: 1,
color: Colors.black,
),
borderRadius: BorderRadius.all(Radius.circular(10)),
);
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: NestedScrollView(
headerSliverBuilder: (context, innerBoxIsScrolled) => [
SliverAppBar(
snap: true,
floating: true,
pinned: false,
toolbarHeight: 80,
title: Text("Home"),
// title: Search(),
centerTitle: true,
bottom: PreferredSize(
preferredSize: Size(0.0, 48.0),
child: Container(
decoration: buildTabBarStyle(),
alignment: Alignment.center,
width: double.infinity,
child: TabBar(
controller: controller,
isScrollable: true,
labelColor: Colors.green,
unselectedLabelColor: Colors.grey,
labelStyle:
TextStyle(fontWeight: FontWeight.bold, fontSize: 16.0),
tabs: [
Tab(text: "1"),
Tab(text: "2"),
Tab(text: "3"),
],
),
),
),
),
],
body: TabBarView(
controller: controller,
children: [
...List.generate(
3,
(t) => Container(
color: Colors.red,
child: ListView.builder(
itemCount: 50,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 60,
color: Colors.blue,
child: Center(
child: Text("tab $t index $index"),
),
),
);
},
),
),
).toList(),
],
),
),
),
);
}
}

No TabController for TabBarView flutter

I am trying add TabBar by using the below code:
TabBarView(
children: [
Icon(Icons.directions_car),
Icon(Icons.directions_transit),
Icon(Icons.directions_bike),
],
),
but I found the below error:
No TabController for TabBarView.
and this is whole code:
import '../providers/properties.dart';
import '../providers/cities.dart';
import '../providers/property.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../widgets/properties_grid.dart';
import '../app_theme.dart';
class MyHomePage extends StatefulWidget {
const MyHomePage({Key key}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
int currentTab = 0;
final PageStorageBucket bucket = PageStorageBucket();
var _showOnlyFavorites = false;
// List<HomeList> homeList = HomeList.homeList;
AnimationController animationController;
bool multiple = true;
#override
void initState() {
animationController = AnimationController(
duration: const Duration(milliseconds: 2000), vsync: this);
super.initState();
}
Future<bool> getData() async {
await Future<dynamic>.delayed(const Duration(milliseconds: 0));
return true;
}
#override
void dispose() {
animationController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
// final properties = Provider.of<Properties>(context, listen: false);
return Scaffold(
extendBody: true,
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {},
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
bottomNavigationBar: BottomAppBar(
elevation: 0,
shape: CircularNotchedRectangle(),
notchMargin: 10,
child: Container(
height: 60,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
MaterialButton(
padding: EdgeInsets.all(0),
minWidth: 155,
onPressed: () {
setState(() {
// currentScreen =
// Chat(); // if user taps on this dashboard tab will be active
currentTab = 1;
});
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
Icons.home,
color: currentTab == 1 ? Colors.blue : Colors.grey,
),
Text(
'Home',
style: TextStyle(
color: currentTab == 1 ? Colors.blue : Colors.grey,
),
),
],
),
)
],
),
// Right Tab bar icons
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
MaterialButton(
padding: EdgeInsets.all(0),
minWidth: 60,
onPressed: () {
setState(() {
// currentScreen =
// Settings(); // if user taps on this dashboard tab will be active
currentTab = 3;
});
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
Icons.view_list,
color: currentTab == 3 ? Colors.blue : Colors.grey,
),
Text(
'Property List',
style: TextStyle(
color: currentTab == 3 ? Colors.blue : Colors.grey,
),
),
],
),
),
MaterialButton(
padding: EdgeInsets.all(0),
minWidth: 77,
onPressed: () {
setState(() {
// currentScreen =
// Settings(); // if user taps on this dashboard tab will be active
currentTab = 4;
});
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
Icons.location_searching,
color: currentTab == 4 ? Colors.blue : Colors.grey,
),
Text(
'Map',
style: TextStyle(
color: currentTab == 4 ? Colors.blue : Colors.grey,
),
),
],
),
),
],
)
],
),
),
),
backgroundColor: AppTheme.white,
body: Stack(
children: <Widget>[
FutureBuilder<bool>(
future: getData(),
builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
if (!snapshot.hasData) {
return const SizedBox();
} else {
return Padding(
padding:
EdgeInsets.only(top: MediaQuery.of(context).padding.top),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
appBar(),
TabBarView(
children: [
Icon(Icons.directions_car),
Icon(Icons.directions_transit),
Icon(Icons.directions_bike),
],
),
Expanded(
child: FutureBuilder<bool>(
future: getData(),
builder: (BuildContext context,
AsyncSnapshot<bool> snapshot) {
if (!snapshot.hasData) {
return const SizedBox();
} else {
return ChangeNotifierProvider(
create: (context) => Properties(),
child: PropertiesGrid(_showOnlyFavorites),
);
}
},
),
),
],
),
);
}
},
),
],
),
);
}
Widget appBar() {
return SizedBox(
height: AppBar().preferredSize.height,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 8, left: 8),
child: Container(
width: AppBar().preferredSize.height - 8,
height: AppBar().preferredSize.height - 8,
),
),
Expanded(
child: Center(
child: Padding(
padding: const EdgeInsets.only(top: 4),
child:
Image.asset('assets/images/logo.png', fit: BoxFit.contain),
),
),
),
Padding(
padding: const EdgeInsets.only(top: 8, right: 8),
child: Container(
width: AppBar().preferredSize.height - 8,
height: AppBar().preferredSize.height - 8,
color: Colors.white,
child: Material(
color: Colors.transparent,
child: InkWell(
borderRadius:
BorderRadius.circular(AppBar().preferredSize.height),
child: Icon(
Icons.location_on,
color: AppTheme.dark_grey,
),
onTap: () {
setState(() {
multiple = !multiple;
});
},
),
),
),
),
],
),
);
}
So How Can I solve this problem...
How can TabBar get to know about the TabBarView? There should be a connection between them to change when tab press or if swap from view right?
So, to connect both two, you have to either wrap your parent widget using DefaultTabController or providing a TabController for TabBar and TabBarView to controll and configure Tabs.
Flutter cookbook example for DefaultTabController:
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: TabBarView(
children: [
Icon(Icons.directions_car),
Icon(Icons.directions_transit),
Icon(Icons.directions_bike),
],
),
),
),
);
}
}
Using TabController(Example from doc):
class MyTabbedPage extends StatefulWidget {
const MyTabbedPage({ Key key }) : super(key: key);
#override
_MyTabbedPageState createState() => _MyTabbedPageState();
}
class _MyTabbedPageState extends State<MyTabbedPage> with SingleTickerProviderStateMixin {
final List<Tab> myTabs = <Tab>[
Tab(text: 'LEFT'),
Tab(text: 'RIGHT'),
];
TabController _tabController;
#override
void initState() {
super.initState();
_tabController = TabController(vsync: this, length: myTabs.length);
}
#override
void dispose() {
_tabController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
bottom: TabBar(
controller: _tabController,
tabs: myTabs,
),
),
body: TabBarView(
controller: _tabController,
children: myTabs.map((Tab tab) {
final String label = tab.text.toLowerCase();
return Center(
child: Text(
'This is the $label tab',
style: const TextStyle(fontSize: 36),
),
);
}).toList(),
),
);
}
}

Back button leads to a very first page

I use a DefaultTabController tabbar which looks like this
class MainTabs extends StatelessWidget {
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 3,
child: Scaffold(
appBar: MyAppbar(),
body: TabBarView(
children: [
CardContentPage(title: 'Tab1'),
DeviceContentPage(title: 'Tab2'),
SettingsPage(title: 'Tab2'),
],
),
),
);
}
}
But with this design the back button always leads to a very first page of the application.
How can I set up it so that back button works as expected with DefaultTabController?
Using a DefaultTabController you can just prevent the user from return, using the WillPopScope:
DefaultTabController(
initialIndex: 0,
length: 3,
child: WillPopScope(
onWillPop: () async {
return false;
},
child: Scaffold(
appBar: AppBar(
bottom: TabBar(tabs: [
Tab(text: 'First',),
Tab(text: 'Second',),
Tab(text: 'Third',),
]),
),
body: TabBarView(
children: [
Container(color: Colors.red,),
Container(color: Colors.yellow,),
Container(color: Colors.green,),
],
),
),
),
);
But with a TabController you can set the route to the previous page:
class TabPage extends StatefulWidget {
#override
_TabPageState createState() => _TabPageState();
}
class _TabPageState extends State<TabPage> with SingleTickerProviderStateMixin {
TabController tabController;
#override
void initState() {
tabController = TabController(length: 3, vsync: this);
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
bottom: TabBar(
controller: tabController,
tabs: [
Tab(
text: 'First',
),
Tab(
text: 'Second',
),
Tab(
text: 'Third',
),
],
),
),
body: TabBarView(
controller: tabController,
children: [
Container(
color: Colors.red,
),
WillPopScope(
onWillPop: () async {
tabController.animateTo(0, duration: Duration(milliseconds: 500),);
return false;
},
child: Container(
color: Colors.yellow,
),
),
WillPopScope(
onWillPop: ()async {
tabController.animateTo(1, duration: Duration(milliseconds: 500),);
return false;
},
child: Container(
color: Colors.green,
),
),
],
),
);
}
}

How to remove extra bottom space in SliverAppBar

I was trying to remove the extra space at the bottom of the SliverAppBar.
My code is:
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> with TickerProviderStateMixin {
ScrollController _scrollViewController;
TabController _tabController;
double scrollPosition;
#override
void initState() {
_scrollViewController = ScrollController();
_tabController = TabController(vsync: this, length: 2, initialIndex: 0)
..addListener(() => _scrollViewController.animateTo(
0.0,
curve: Curves.easeIn,
duration: const Duration(milliseconds: 300),
));
super.initState();
}
#override
void dispose() {
_tabController.dispose();
_scrollViewController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
child: DefaultTabController(
length: 2,
initialIndex: 0,
child: Scaffold(
body: NestedScrollView(
controller: _scrollViewController,
headerSliverBuilder:
(BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
title: InkWell(
child: const Text(kCandice, style: kLogoText),
onTap: () => scrollToTop(),
),
centerTitle: true,
elevation: 0,
backgroundColor: Colors.white,
pinned: true,
floating: true,
snap: true,
forceElevated: innerBoxIsScrolled,
bottom: TabBar(
tabs: <Tab>[
Tab(
text:
AppLocalizations.of(context).translate('following'),
),
Tab(
text:
AppLocalizations.of(context).translate('trending'),
)
],
unselectedLabelColor: Colors.black54,
labelColor: kPink,
unselectedLabelStyle: kMediumBoldText,
labelStyle: kMediumBoldText,
indicatorSize: TabBarIndicatorSize.tab,
indicatorColor: Colors.transparent,
controller: _tabController,
),
),
];
},
body: TabBarView(
children: [
PostSection(), // TODO: Following
PostSection(), // TODO: Trending
],
),
),
),
),
);
}
void scrollToTop() {
_scrollViewController.animateTo(
0.0,
curve: Curves.easeOut,
duration: const Duration(milliseconds: 300),
);
}
}
The solution I found:
MediaQuery.removePadding(
context: context,
removeTop: true,
child: Padding(
padding: const EdgeInsets.only(top: kCommonSeparation),
child: TabBarView(
children: [
PostSection(), // TODO: Following
PostSection(), // TODO: Trending
],
),
),
),

how to make tabview inside another tabview in flutter?

I tried to create nested tabs bar views in the following way, by returning a column containing another tab view from the outer tab view, however it just shows a blank screen instead of the second tab view. How can I fix this?
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: DefaultTabController(length: 2, child: MyHomePage(title: '')),
);
}
}
class MyHomePage extends StatelessWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
Widget build(BuildContext context){
final view = LayoutBuilder(builder: (context, constraints){
//created a widget here with content
});
return Scaffold(
appBar: AppBar(
title: Text('Tab bar view'), bottom: TabBar(
tabs: [
Tab(icon: Icon(Icons.directions_car)),
Tab(icon: Icon(Icons.directions_transit)),
]),
),
body: TabBarView(children: [DefaultTabController(length: 2, child: Column(
children: <Widget>[TabBar(tabs: [Tab(text: 'Home'),Tab(text: 'News')
, Container(child: TabBarView(
children: <Widget>[ view, Icon(Icons.access_alarms)],
))])]
) ), Icon(Icons.directions_car)]));
}
}
Best Way to do it just like in Google Play store.
import 'package:flutter/material.dart';
class Locationstat extends StatefulWidget {
#override
_LocationstatState createState() => _LocationstatState();
}
class _LocationstatState extends State<Locationstat>
with SingleTickerProviderStateMixin {
late TabController _tabController;
#override
void initState() {
super.initState();
_tabController = new TabController(length: 2, vsync: this);
}
#override
void dispose() {
super.dispose();
_tabController.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
elevation: 0,
title: Text('Statistics'),
bottom: TabBar(
controller: _tabController,
indicatorColor: Colors.orange,
labelColor: Colors.orange,
unselectedLabelColor: Colors.black54,
tabs: <Widget>[
Tab(
text:('Pokhara Lekhnath'),
),
Tab(
text:('Outside Pokhara-Lekhnath'),
),
]),
),
body: TabBarView(
children: <Widget>[
NestedTabBar(),
NestedTabBar(),
],
controller: _tabController,
),
);
}
}
class NestedTabBar extends StatefulWidget {
#override
_NestedTabBarState createState() => _NestedTabBarState();
}
class _NestedTabBarState extends State<NestedTabBar>
with TickerProviderStateMixin {
late TabController _nestedTabController;
#override
void initState() {
super.initState();
_nestedTabController = new TabController(length: 2, vsync: this);
}
#override
void dispose() {
super.dispose();
_nestedTabController.dispose();
}
#override
Widget build(BuildContext context) {
double screenHeight = MediaQuery.of(context).size.height;
return Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
TabBar(
controller: _nestedTabController,
indicatorColor: Colors.orange,
labelColor: Colors.orange,
unselectedLabelColor: Colors.black54,
isScrollable: true,
tabs: <Widget>[
Tab(
text: "Inside Pokhara",
),
Tab(
text: "Outside Pokhara",
),
],
),
Container(
height: screenHeight * 0.70,
margin: EdgeInsets.only(left: 16.0, right: 16.0),
child: TabBarView(
controller: _nestedTabController,
children: <Widget>[
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.0),
color: Colors.blueGrey[300],
),
),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.0),
color: Colors.blueGrey[300],
),
),
],
),
)
],
);
}
}
import 'package:flutter/material.dart';
class Locationstat extends StatefulWidget {
#override
_LocationstatState createState() => _LocationstatState();
}
class _LocationstatState extends State<Locationstat>
with SingleTickerProviderStateMixin {
TabController _tabController;
#override
void initState() {
super.initState();
_tabController = new TabController(length: 2, vsync: this);
}
#override
void dispose() {
super.dispose();
_tabController.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
elevation: 0,
title: Text('Statistics'),
bottom: TabBar(
controller: _tabController,
indicatorColor: Colors.orange,
labelColor: Colors.orange,
unselectedLabelColor: Colors.black54,
tabs: <Widget>[
Tab(
text:('Pokhara Lekhnath'),
),
Tab(
text:('Outside Pokhara-Lekhnath'),
),
]),
),
body: TabBarView(
children: <Widget>[
NestedTabBar(),
NestedTabBar(),
],
controller: _tabController,
),
);
}
}
class NestedTabBar extends StatefulWidget {
#override
_NestedTabBarState createState() => _NestedTabBarState();
}
class _NestedTabBarState extends State<NestedTabBar>
with TickerProviderStateMixin {
TabController _nestedTabController;
#override
void initState() {
super.initState();
_nestedTabController = new TabController(length: 2, vsync: this);
}
#override
void dispose() {
super.dispose();
_nestedTabController.dispose();
}
#override
Widget build(BuildContext context) {
double screenHeight = MediaQuery.of(context).size.height;
return Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
TabBar(
controller: _nestedTabController,
indicatorColor: Colors.orange,
labelColor: Colors.orange,
unselectedLabelColor: Colors.black54,
isScrollable: true,
tabs: <Widget>[
Tab(
text: "Inside Pokhara",
),
Tab(
text: "Outside Pokhara",
),
],
),
Container(
height: screenHeight * 0.70,
margin: EdgeInsets.only(left: 16.0, right: 16.0),
child: TabBarView(
controller: _nestedTabController,
children: <Widget>[
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.0),
color: Colors.blueGrey[300],
),
),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.0),
color: Colors.blueGrey[300],
),
),
],
),
)
],
);
}
}
you can do that by adding BottomNavigationBar to the Scaffold and route to a widget that contains the TabBar
Check this, https://github.com/whatsupcoders/Flutter-Nested-Tabs
It has code, which has a UI replication of the Google Play Store.
Here' the image
Here's the tutorial for it: https://www.youtube.com/watch?v=bSywfMPuwaw
Cheers!