How to solve overflow issues in flutter tabs? - flutter

Following is a custom tab I've created:
class Tabs extends StatefulWidget {
final tabs;
final views;
Tabs({this.tabs, this.views});
#override
_TabsState createState() => _TabsState();
}
class _TabsState extends State<Tabs> with SingleTickerProviderStateMixin {
late TabController _tabController;
#override
void initState() {
_tabController = TabController(length: widget.tabs.length, vsync: this);
super.initState();
}
#override
void dispose() {
super.dispose();
_tabController.dispose();
}
#override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
return SingleChildScrollView(
physics: BouncingScrollPhysics(),
child: Container(
height: size.height,
child: Column(
children: [
Container(
height: 45,
decoration: BoxDecoration(
border: Border(
bottom:
BorderSide(color: Colors.grey, width: 3),
),
),
child: TabBar(
isScrollable: true,
controller: _tabController,
indicatorPadding: EdgeInsets.only(bottom: -2.5),
indicator: UnderlineTabIndicator(
borderSide: BorderSide(
width: 4,
color: Colors.blue,
),
),
labelColor: Colors.blue,
unselectedLabelColor: Colors.black,
tabs: [
...widget.tabs.map(
(e) => Tab(
child: Container(
child: Text(
e,
style: GoogleFonts.inter(
fontSize: 14,
fontWeight: FontWeight.w600,
),
),
),
),
)
],
),
),
Expanded(
child: TabBarView(
controller: _tabController,
children: [...widget.views],
),
),
],
),
),
);
}
}
But as soon as I use it inside my app screen, I'm getting overflow issues:
class Home extends StatelessWidget {
const Home({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: "Home"
elevation: 0,
toolbarHeight: 36,
),
drawer: DrawerNavigation(),
body: SingleChildScrollView(
physics: BouncingScrollPhysics(),
child: Column(
children: [
SizedBox(
height: 100,
),
Tabs(
tabs: ['tab1', 'tab2'],
views: [
Tab1(),
Tab2(),
],
),
],
),
),
);
}
}
The error I'm getting from is from single child scroll view.
I've tried removing single child scroll view from the tabs, but then the custom tabs wont' work.

just remove single child scroll view from custom Tab like this,
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
class Tabs extends StatefulWidget {
final tabs;
final views;
Tabs({this.tabs, this.views});
#override
_TabsState createState() => _TabsState();
}
class _TabsState extends State<Tabs> with SingleTickerProviderStateMixin {
late TabController _tabController;
#override
void initState() {
_tabController = TabController(length: widget.tabs.length, vsync: this);
super.initState();
}
#override
void dispose() {
super.dispose();
_tabController.dispose();
}
#override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
return Container(
height: size.height,
child: Column(
children: [
Container(
height: 45,
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(color: Colors.grey, width: 3),
),
),
child: TabBar(
isScrollable: true,
controller: _tabController,
indicatorPadding: EdgeInsets.only(bottom: -2.5),
indicator: UnderlineTabIndicator(
borderSide: BorderSide(
width: 4,
color: Colors.blue,
),
),
labelColor: Colors.blue,
unselectedLabelColor: Colors.black,
tabs: [
...widget.tabs.map(
(e) => Tab(
child: Container(
child: Text(
e,
style: GoogleFonts.inter(
fontSize: 14,
fontWeight: FontWeight.w600,
),
),
),
),
)
],
),
),
Expanded(
child: TabBarView(
controller: _tabController,
children: [...widget.views],
),
),
],
),
);
}
}
and convert stateless widget (Home) into stateful widget and it will work fine like this,
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Column(
children: [
SizedBox(
height: 100,
),
Tabs(
tabs: ["tab1", "tab2"],
views: [okay(), okay()],
)
],
),
),
);
}
}

Related

How to implement custom tab in flutter

I want something like this.
Im able to implement something similar with SwitchTab,but not able to use gradient color for selected tab.
Please help
SwitchTab(
text: const [ "Personal",
"Group",
],
selectedTextColor: Colors.black,
unselectedTextColor:Colors.white,
shape: SwitchTabShape.rounded,
thumbColor: Colors.white,
backgroundColour:
Color.fromARGB(255, 31, 89, 169),
onValueChanged: (index) {
setState(() {
selected = index;
});
},
),
You can use a combination of a normal TabBar, BoxDecoration and LinearGradient for this:
Code Example:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatefulWidget {
#override
MyWidgetState createState() => MyWidgetState();
}
class MyWidgetState extends State<MyWidget>
with SingleTickerProviderStateMixin {
late TabController _tabController;
#override
void initState() {
_tabController = TabController(length: 2, vsync: this);
super.initState();
}
#override
void dispose() {
super.dispose();
_tabController.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Stack Overflow Example'),
),
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
Container(
height: 45,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(
25.0,
),
),
child: TabBar(
controller: _tabController,
indicator: BoxDecoration(
borderRadius: BorderRadius.circular(
25.0,
),
color: Colors.green,
gradient: LinearGradient(
begin: Alignment.topRight,
end: Alignment.bottomLeft,
colors: [
Colors.pink,
Colors.deepPurple,
],
),
),
labelColor: Colors.white,
unselectedLabelColor: Colors.black,
tabs: [
const Tab(text: 'Personal'),
const Tab(text: 'Group'),
],
),
),
Expanded(
child: TabBarView(
controller: _tabController,
children: [
Center(child: Text('Personal Content')),
Center(child: Text('Group Content')),
],
),
),
],
),
),
);
}
}

Can i wrap tab bar using widget chip

I want to do when I click on each chip, it will change the content of my body but I am using tab controller which I wrap with chip widget.
I also want to decorate my chip when it is selected and unselected. I try to declare my text for each widget using list array but I am stuck. Can someone help me. This is what I have been done so far
class YearTab extends StatefulWidget {
const YearTab({
Key? key,
}) : super(key: key);
#override
State<YearTab> createState() => _YearTabState();
}
class _YearTabState extends State<YearTab>
with SingleTickerProviderStateMixin {
late TabController _controller;
bool _selectedTab = false;
List<Widget> list = const [
Chip(label: Text('This year')),
Chip(label: Text('2021')),
Chip(label: Text('2020')),
Chip(label: Text('2019')),
Chip(label: Text('2018')),
];
#override
void initState() {
super.initState();
_controller = TabController(length: list.length, vsync: this);
}
#override
Widget build(BuildContext context) {
return Column(
children: [
Container(
color: AppColor.white,
width: MediaQuery.of(context).size.width,
child: TabBar(
// unselectedLabelColor: Colors.yellow,
// labelColor: Colors.red,
physics: const BouncingScrollPhysics(),
indicator: BoxDecoration(
border: Border.all(color: Colors.red),
borderRadius: BorderRadius.circular(10),
color: const Color.fromARGB(255, 176, 208, 255)
// color: !widget.selected
// ? Color.fromARGB(255, 176, 208, 255)
// : Colors.transparent
),
controller: _controller,
onTap: (index) {},
isScrollable: true,
tabs: list,
)),
SizedBox(
height: MediaQuery.of(context).size.height * 2.2,
child: TabBarView(
controller: _controller,
children: const [
//Content for Demografi Pengguna
Content1(),
Content2(),
Content3(),
Content4(),
Content5(),
],
),
)
],
);
}
}
Instead of Tabview ,you can use this :
dependencies:
toggle_switch: ^2.0.1
Example:
ToggleSwitch(
minWidth: 90.0,
initialLabelIndex: 1,
cornerRadius: 20.0,
activeFgColor: Colors.white,
inactiveBgColor: Colors.grey,
inactiveFgColor: Colors.white,
totalSwitches: 2,
labels: ['Tab1', 'Tab2'],
icons: [FontAwesomeIcons.mars, FontAwesomeIcons.venus],
activeBgColors: [[Colors.blue],[Colors.pink]],
onToggle: (index) {
print('switched to: $index');
//change the view as per index
},
),
When you request a chip widget, it is called in initState() the first time you call the widget. You can initialize the array from there and get the data. Alternatively, you can call the widget by observing the array using the Stream structure using getX or Provider.
i changed a few things
class YearTab extends StatefulWidget {
const YearTab({
Key? key,
}) : super(key: key);
#override
State<YearTab> createState() => _YearTabState();
}
class _YearTabState extends State<YearTab> with SingleTickerProviderStateMixin {
List<Widget> tabs = const [
Chip(label: Text('This year')),
Chip(label: Text('2021')),
Chip(label: Text('2020')),
Chip(label: Text('2019')),
Chip(label: Text('2018')),
];
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: tabs.length,
child: Scaffold(
appBar: AppBar(
bottom: TabBar(
indicatorColor: Theme.of(context).colorScheme.secondary,
tabs: tabs,
),
),
body: TabBarView(
children: [
//Content for Demografi Pengguna
Container(
color: Colors.blueAccent,
),
Container(
color: Colors.red,
),
Container(
color: Colors.green,
),
Container(
color: Colors.yellow,
),
Container(
color: Colors.grey,
),
],
),
),
);
}
}

How to use multiple tab for single page in Flutter

I create Tab Bar for my project. It includes two tabs and these each tabs are represent two pages.
Here is the code
import 'package:flutter/material.dart';
class TabView extends StatefulWidget {
#override
_TabViewState createState() => _TabViewState();
}
class _TabViewState extends State<TabView> with SingleTickerProviderStateMixin {
TabController _tabController;
#override
void initState() {
_tabController = TabController(length: 2, vsync: this);
super.initState();
}
#override
void dispose() {
super.dispose();
_tabController.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey.shade300,
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Container(
height: 45,
decoration: BoxDecoration(
color: Colors.grey.shade300,
borderRadius: BorderRadius.circular(
16.0,
),
),
child: TabBar(
controller: _tabController,
indicator: BoxDecoration(
borderRadius: BorderRadius.circular(
16.0,
),
color: Colors.grey.shade900,
),
labelColor: Colors.white,
unselectedLabelColor: Colors.grey.shade900,
tabs: [
Tab(
text: 'One',
),
Tab(
text: 'Two',
),
],
),
),
Expanded(
child: TabBarView(
controller: _tabController,
children: [
Center(
child: Text(
'Page One',
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.w600,
),
),
),
Center(
child: Text(
'Page Two',
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.w600,
),
),
),
],
),
),
],
),
),
),
);
}
}
Here is output
I want to use the tab bar for a single page to change a widget state.
Example
I want use the tab bar to change the color of the container in page one from red to blue and I don't want to switch to page two
How can I do it?
TabBar is not quite suitable for this purpose, although it can be adapted. I suggest you to use CupertinoSegmentedControl from cupertino package. Here is docs, and here is code example:
enum _Tab { one, two }
class MyWidget extends StatefulWidget {
#override
State<StatefulWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
_Tab _selectedTab = _Tab.one;
#override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
SizedBox(height: 16),
CupertinoSegmentedControl<_Tab>(
selectedColor: Colors.black,
borderColor: Colors.black,
pressedColor: Colors.grey,
children: {
_Tab.one: Text('One'),
_Tab.two: Text('Two'),
},
onValueChanged: (value) {
setState(() {
_selectedTab = value;
});
},
groupValue: _selectedTab,
),
SizedBox(height: 64),
Builder(
builder: (context) {
switch (_selectedTab) {
case _Tab.one:
return Center(
child: Container(
width: 100,
height: 100,
color: Colors.red,
),
);
case _Tab.two:
return Center(
child: Container(
width: 100,
height: 100,
color: Colors.blue,
),
);
}
},
),
],
);
}
}
Also take a look at CupertinoSlidingSegmentedControl.
for your requirement don't use TabBarView at all, directly use container, change it's color value as per selectedtab index
class Tabscreenstate extends State<Tabscreen> with TickerProviderStateMixin {
int selectedTabIndex = 0;
TabController tabController;
#override
void initState() {
tabController = TabController(length: 2, vsync: this);
tabController.addListener(() {
setState(() {
selectedTabIndex = tabController.index;
});
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Column(
children: [
tabbar(),
Container(color:selectedTabIndex == 0 ? Colors.red : Colors.green),
],
);
}
Widget tabbar() => TabBar(
controller: tabController,
onTap: (value) {
setState(() {
selectedTabIndex = value;
});
},
tabs: [
Text("tab one"),
Text("tab two"),
],
);
}

Flutter how to create clickable tabs

How to create basic design like from sketch from image. First container with list of tabs is static, and containers above it is dynamic, and contain text - Text for tab 1 if tab 1 is clicked, or Text for tab 2 if tab 2 is clicked. Also text for Tab1 or Tab2 must be underline if we click on it.
Something like this:
Using a GestureDetector widget to tell when a user taps on the tabs and then updating the state with setState is maybe the most simple way of doing this.
Here is a very basic example of using a stateful widget and setState to update the page. You can approach this problem with any state management strategy, though.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: Scaffold(body: MyHomePage()),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String selectedTab;
static const String TAB_1 = 'Tab 1';
static const String TAB_2 = 'Tab 2';
#override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
flex: 1,
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
GestureDetector(
onTap: () {
setState(() => selectedTab = TAB_1);
},
child: Container(
padding: const EdgeInsets.all(12.0),
child: Text(TAB_1),
decoration: selectedTab == TAB_1
? BoxDecoration(border: Border(bottom: BorderSide()))
: null,
),
),
GestureDetector(
onTap: () {
setState(() => selectedTab = TAB_2);
},
child: Container(
padding: const EdgeInsets.all(12.0),
child: Text(TAB_2),
decoration: selectedTab == TAB_2
? BoxDecoration(border: Border(bottom: BorderSide()))
: null,
),
)
],
),
),
Container(height: 20.0),
Expanded(
flex: 2,
child: Container(
decoration: BoxDecoration(
border: Border.all(width: 5),
borderRadius: BorderRadius.circular(12.0)),
child: Center(child: Text(textForTab(selectedTab))),
),
)
],
);
}
String textForTab(String tabId) {
switch (tabId) {
case TAB_1:
return 'Text for Tab 1';
case TAB_2:
return 'Text for Tab 2';
default:
return 'Select Tab';
}
}
}
You can do it using TabBar widget.
class CustomTabBar extends StatefulWidget {
#override
_CustomTabBarState createState() => _CustomTabBarState();
}
class _CustomTabBarState extends State<CustomTabBar>
with SingleTickerProviderStateMixin {
TabController _tabController;
#override
void initState() {
_tabController = TabController(length: 2, vsync: this);
super.initState();
}
#override
void dispose() {
super.dispose();
_tabController.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'Tab Demo',
),
),
body:
Column(
children: [
Container(
height: 45,
child: TabBar(
controller: _tabController,
indicator: BoxDecoration(
border: Border(bottom: BorderSide(color: Colors.blue,width: 2,style:
BorderStyle.solid)),
),
labelColor: Colors.blue,
unselectedLabelColor: Colors.black,
tabs: [
// first tab
Tab(
text: 'Home',
),
// second tab
Tab(
text: 'Profile',
),
],
),
),
// tab bar view
Expanded(
child: TabBarView(
controller: _tabController,
children: [
// first tab widget
Center(
child: Text(
'Home',
style: TextStyle(
fontSize: 26,
fontWeight: FontWeight.bold,
),
),
),
// Second tab widget
Center(
child: Text(
'Profile',
style: TextStyle(
fontSize: 26,
fontWeight: FontWeight.bold,
),
),
),
],
),
),
],
),
);
}
}
I'm not sure I understand you completely.
But if you want to implement a TabBar, you can use flutter TabBar() documented here:
https://flutter.dev/docs/cookbook/design/tabs
Or there is a package you can use:
https://pub.dev/packages/tabbar

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!