import 'dart:ffi';
import 'package:flutter/material.dart';
import 'package:whatsapp_clone/chatScreen.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin{
late TabController _tabcontroller;
#override
void initState(){
super.initState();
_tabcontroller=TabController(length: 4, vsync: this, initialIndex: 1);
}
#override
void dispose(){
_tabcontroller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Color(0xff075E54),
title: const Text('Whatsapp Clone'),
actions: [IconButton(onPressed: (){}, icon: const Icon(Icons.search)),
PopupMenuButton(onSelected: (value){print(value);},
itemBuilder: (BuildContext context){return [
PopupMenuItem(child: Text('New Group'),value: 'New Group'),
PopupMenuItem(child: Text('New Broadcast'),value: 'New Broadcast'),
PopupMenuItem(child: Text('Whatsapp web'),value: 'Whatsapp web'),
PopupMenuItem(child: Text('Starred messages'),value: 'Starred messages'),
PopupMenuItem(child: Text('Settings'),value: 'Settings')
];
}
),
],
bottom: TabBar(
controller: _tabcontroller,
tabs: const [
Tab(icon: Icon(Icons.camera_alt)),
Tab(text:'CHAT'),
Tab(text: 'STATUS'),
Tab(text: 'CALLS')
],
indicatorColor: Colors.white,
),
),
body: TabBarView(controller: _tabcontroller,
children: const [
Text('camera'),
ChatPage(),
Text('status'),
Text('calls')
],
),
);
}
}
I want to show the chatscreen which is at 1 index, when opening the app, and i have given the initial index to 1 also, but whenever i open my app, although the chat tabbar was selected but the content was showing from first screen. how can i solve this problem
Related
I am trying to build simple TabBar but getting an error
missing the concrete implementation of 'State.build' and the declaration 'build isn't referenced' . I have created the controller and trying to change to each tab when pressed on individuals.
I have created there tab and provided different function to them.
By clicking the Tab it will not change. I donot know where I am getting wrong?
Thank you in advance.
import 'package:flutter/material.dart';
import 'homepage.dart';
import 'secondpage.dart';
import 'thirdpage.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
static const appTitle = 'Drawer Demo';
#override
Widget build(BuildContext context) {
return const MaterialApp(
title: appTitle,
debugShowCheckedModeBanner: false,
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
late TabController controller;
#override
void initState() {
super.initState();
controller = TabController(length: 3, vsync: this);
controller.addListener(() {
setState(() {});
});
}
#override
void dispose() {
super.initState();
controller.dispose();
super.dispose();
#override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
leading: Icon(Icons.menu),
title: Text('Tab ${controller.index + 1}'),
centerTitle: true,
backgroundColor: Colors.purple,
elevation: 20,
//titleSpacing: 0,
bottom: TabBar(
controller: controller,
tabs: const [
Tab(
text: 'Home',
icon: Icon(Icons.home),
),
Tab(
text: 'Page1',
icon: Icon(Icons.star),
),
Tab(
text: 'Page2',
icon: Icon(Icons.person),
),
],
),
),
body: TabBarView(
controller: controller,
children: const [
HomePage(),
SecondPage(),
ThirdPage(),
],
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add, size: 32),
onPressed: () {
controller.animateTo(0);
}
),
);
}
}
You should declare _MyHomePageState class inside
build widget
Widget build(BuildContext context) {
// TODO: implement build
throw UnimplementedError();
}
But you did inside void dispose() {} Method.
in-app bottom bar I want to add an underline for specifically selected icon. Is there any way for BottomNavigationBarItem or do I need to use a different widget?
class CustomAppBottomBar extends StatefulWidget {
const CustomAppBottomBar({Key? key}) : super(key: key);
#override
State<CustomAppBottomBar> createState() => _CustomAppBottomBarState();
}
class _CustomAppBottomBarState extends State<CustomAppBottomBar> {
int _currentIndex = 0;
#override
Widget build(BuildContext context) {
return BottomNavigationBar(
showUnselectedLabels: true,
showSelectedLabels: true,
type: BottomNavigationBarType.fixed,
selectedItemColor: RJDriverColors.primary,
unselectedItemColor: RJDriverColors.bottomBarSecondary,
selectedFontSize: 12,
unselectedFontSize: 12,
currentIndex: _currentIndex,
onTap: (value) {
setState(() {
_currentIndex = value;
});
},
Try using 'TabBar' and use onTap as onChanged since they are both of type ValueChanged<int>
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
late final TabController controller;
#override
void initState() {
controller = TabController(length: 4, vsync: this);
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
bottomNavigationBar: TabBar(
controller: controller,
unselectedLabelColor: Colors.grey,
labelColor: Colors.blue,
onTap: (index) {},
tabs: const [
Tab(icon: Icon(Icons.menu_rounded)),
Tab(icon: Icon(Icons.piano)),
Tab(icon: Icon(Icons.car_rental_rounded)),
Tab(icon: Icon(Icons.settings_rounded)),
],
),
);
}
}
Using Tabbar with DefaultTabController you can get your desired result. I'm sharing a reference code you can customize it as per your need.
return DefaultTabController(
length: 4,
child: Scaffold(
body: TabBarView(
children: [
Center(
child: Text("1st Screen"),
),
Center(
child: Text("2nd Screen"),
),
Center(
child: Text("3rd Screen"),
),
Center(
child: Text("4th Screen"),
),
],
),
bottomNavigationBar: TabBar(
labelColor: Colors.red,
tabs: [
Tab(child: Icon(Icons.more_vert_sharp),),
Tab(child: Icon(Icons.local_play_sharp),),
Tab(child: Icon(Icons.directions_car),),
Tab(child: Icon(Icons.home),),
]),
),
);
Any code example is welcome, thanks!
TabBar does this animation by default...
You can look at its source code from the IDE or here to see how it's done.
This page has documentation, video, and examples if you want to use it directly in your app.
Here is the code sample.
You can use TabBar widget.
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
late TabController _tabController;
#override
void initState() {
super.initState();
_tabController = TabController(length: 3, vsync: this, initialIndex: 0);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.black,
title: Text("Demo"),
bottom: TabBar(
controller: _tabController,
indicatorColor: Colors.white,
tabs: [
Tab(
text: "Wellbeing",
),
Tab(
text: "Cleaning",
),
Tab(
text: "Self-care",
),
],
),
),
body: TabBarView(
controller: _tabController,
children: [
Center(child: Text("Wellbeing")),
Center(child: Text("Cleaning")),
Center(child: Text("Self-care")),
],
),
);
}
}
I have design like above , my tabbar is inside BottomNavigationBar and i want place the tabbar in my BottomNavigationBar menu. The problem is , i don't want have nested scaffold and i don't want use TabController because my tabs is dynamic , tabs length can be decrease or increase depending of user adding it. If i use TabController and define it inside initState , the tabs can't be increase/decrease because in initState only once define the value.
How can i do this ?
My expectation similiar in below example , when i adding tab and tabMenu it will increase . But get this error
The following assertion was thrown building TabBar(dirty, dependencies: [_InheritedTheme,
_LocalizationsScope-[GlobalKey#a56a4]], state: _TabBarState#fb337):
Controller's length property (2) does not match the number of tabs (3) present in TabBar's tabs
property.
The relevant error-causing widget was:
TabBar
Dummy Example
class TaskScreen extends StatefulWidget {
#override
_TaskScreenState createState() => _TaskScreenState();
}
class _TaskScreenState extends State<TaskScreen> with SingleTickerProviderStateMixin {
TabController _tabController;
final List<Tab> _tab = [
Tab(text: 'Sunday'),
Tab(text: 'Monday'),
];
final List<Widget> _tabMenu = [
Text('This is Sunday'),
Text('This is Monday'),
];
#override
void initState() {
super.initState();
_tabController = TabController(length: _tab.length, vsync: this);
}
#override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
FlatButton(
onPressed: () {
setState(() {
_tab.add(Tab(
text: '1',
));
_tabMenu.add(Text('1'));
});
print('tab ${_tab.length}');
print('tabMenu ${_tabMenu.length}');
},
child: Text('add')),
Container(
color: colorPallete.primaryColor,
padding: EdgeInsets.only(top: sizes.statusBarHeight(context)),
child: TabBar(
tabs: _tab.map((e) => e).toList(),
controller: _tabController,
),
),
Expanded(
child: TabBarView(
children: _tabMenu.map((e) => e).toList(),
controller: _tabController,
),
)
],
);
}
}
use TickerProviderStateMixin instead of SingleTickerProviderStateMixin
and change TabController on changing tabs number;
add isScrollable: true when you don't have space for all your tabs
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,
),
home: Scaffold(
body: SafeArea(
child: MyHomePage(),
),
),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return TaskScreen();
}
}
class TaskScreen extends StatefulWidget {
#override
_TaskScreenState createState() => _TaskScreenState();
}
class _TaskScreenState extends State<TaskScreen> with TickerProviderStateMixin {
TabController _tabController;
final List<Tab> _tab = [
Tab(text: 'Sunday'),
Tab(text: 'Monday'),
];
final List<Widget> _tabMenu = [
Text('This is Sunday'),
Text('This is Monday'),
];
#override
void initState() {
super.initState();
_tabController = TabController(length: _tab.length, vsync: this);
}
#override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
FlatButton(
onPressed: () {
setState(() {
_tab.add(
Tab(
text: '1',
),
);
_tabMenu.add(
Text('1'),
);
_tabController =
TabController(length: _tab.length, vsync: this);
});
print('tab ${_tab.length}');
print('tabMenu ${_tabMenu.length}');
},
child: Text('add')),
Container(
color: Colors.blue,
padding: EdgeInsets.only(top: 10),
child: TabBar(
// isScrollable: true,
tabs: _tab.map((e) => e).toList(),
controller: _tabController,
),
),
Expanded(
child: TabBarView(
children: _tabMenu.map((e) => e).toList(),
controller: _tabController,
),
)
],
);
}
}
How can I disable TabView animation when Tab in TabBar clicked ?
I added
physics: NeverScrollableScrollPhysics()
for TabView but that doesn't apply for TabBar.
I'm using DefaultTabController.
Based on a very good answer on github about this issue, which achieves something similar to what your looking for (but with a bottomNavigationBar) here I share with you another workaround. It consists of combining a DefaultTabController with a PageView, a PageController and a simple index. Try this out.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Tabs with no animation',
theme: ThemeData.dark(),
home: HomeScreen(),
);
}
}
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
PageController _pageController;
final int currentTab = 0;
#override
void initState() {
// TODO: implement initState
_pageController = PageController(initialPage: currentTab);
super.initState();
}
final List<Tab> myTabs = <Tab>[
Tab(text: 'One'),
Tab(
text: 'Two',
),
];
var tabs = [
TabOne(),
TabTwo(),
];
#override
Widget build(BuildContext context) {
var pageView = PageView(
controller: _pageController,
physics: NeverScrollableScrollPhysics(),
children: tabs,
);
return DefaultTabController(
length: myTabs.length,
child: Scaffold(
extendBodyBehindAppBar: true,
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0.0,
automaticallyImplyLeading: false,
title: Center(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: Colors.grey.shade800,
),
width: 200,
height: 50,
child: TabBar(
onTap: (index) {
_pageController.jumpToPage(index);
},
unselectedLabelColor: Colors.white,
indicator: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: Colors.black),
tabs: myTabs,
),
),
),
),
body: pageView),
);
}
}
class TabOne extends StatelessWidget {
const TabOne({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
child: Center(child: Text('Tab one')),
);
}
}
class TabTwo extends StatelessWidget {
const TabTwo({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
child: Center(child: Text('Tab two')),
);
}
}
Doing so, you have a something identical to a TabBarView but without animation.
I don't think there's a way to disable the transition animation on TabBarView. As a workaround, you can use a Container that'll return different pages depending on the tab selected.
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(
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
#override
void initState() {
super.initState();
tabController = TabController(length: 4, vsync: this);
}
var _homeScaffoldKey = Key("Scaffold Key");
var tabController;
var currentPage = 0;
#override
Widget build(BuildContext context) {
return new Scaffold(
key: _homeScaffoldKey,
body: _getCustomContainer(),
bottomNavigationBar: new Material(
color: Colors.blue,
child: new TabBar(
isScrollable: true,
indicatorColor: Color.fromRGBO(255, 25, 255, 0.0),
controller: tabController,
onTap: (value) {
setState(() {
currentPage = value;
});
},
tabs: <Widget>[
new Tab(
icon: new Icon(Icons.accessibility),
),
new Tab(
icon: new Icon(Icons.accessibility),
),
new Tab(
icon: new Icon(Icons.accessibility),
),
new Tab(
icon: new Icon(Icons.accessibility),
),
],
),
),
);
}
_getCustomContainer() {
switch (currentPage) {
case 0:
return page1();
case 1:
return page2();
case 2:
return page3();
case 3:
return page4();
}
}
page1() => Container(
color: Colors.redAccent,
child: Center(
child: Text("Page 1"),
),
);
page2() => Container(
color: Colors.greenAccent,
child: Center(
child: Text("Page 2"),
),
);
page3() => Container(
color: Colors.blueAccent,
child: Center(
child: Text("Page 3"),
),
);
page4() => Container(
color: Colors.yellowAccent,
child: Center(
child: Text("Page 4"),
),
);
}
Demo
Seems like this can be achieved using DefaultTabController easily as of 2022.
Here is my solution to this:
class _TabPageState extends State<TabPage>
with SingleTickerProviderStateMixin {
late TabController _tabController;
#override
void initState() {
super.initState();
// when initializing the `TabController` set `animationDuration` as `zero`.
_tabController =
TabController(length: 3, vsync: this, animationDuration: Duration.zero);
}
#override
Widget build(BuildContext context) {
return Container(
color: ColorPalette.white,
child: SafeArea(
top: false,
child: DefaultTabController(
length: 3,
child: Builder(builder: (context) {
return Scaffold(
bottomNavigationBar: TabBar(
controller: _tabController, // set the tab controller of your `TabBar`
enableFeedback: false,
onTap: (index) {
setState(() {});
},
indicatorColor: Colors.transparent,
tabs: [
TabItem(
selectedIndex: _tabController.index,
index: 0,
assetName: Assets.tabHome),
TabItem(
selectedIndex: _tabController.index,
index: 1,
assetName: Assets.tabCare),
TabItem(
selectedIndex: _tabController.index,
index: 2,
assetName: Assets.tabProfile),
],
),
body: Center(
child: TabBarView(
controller: _tabController, // set the controller of your `TabBarView`
physics: const NeverScrollableScrollPhysics(),
children: const [
ParentHomePage(),
ParentCarePage(),
ParentAccountPage()
],
),
),
);
}),
),
),
);
}
}
You Can Fix It by Go to MaterialApp and type
theme:new ThemeData(
splashColor:Colors.blue,
highlightColor: Colors.blue
)
what it mean if your tab background color blue you will change splashColor and highlightColor to blue that mean the animation doesn't disabled but it doesn't appear because the animation splashcolor and highlight will be blue such as Tab Background , I Hope I Help You