Newsvoice got a scrollable tabs on the bottom of the screen on top of a bottom bar. How can I implement this UI ?
Thanks.
Here is some example code that uses a Column to position a scrollable TabBar and a BottomNavigationBar in the bottomNavigationBar slot of the Scaffold. Note that the tabs disappear when you select the second ("motorcycle") screen, using an AnimatedCrossFade.
import 'package:flutter/material.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Navigation Example',
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
#override
_MyHomePageState createState() => new _MyHomePageState();
}
const List<String> tabNames = const<String>[
'foo', 'bar', 'baz', 'quox', 'quuz', 'corge', 'grault', 'garply', 'waldo'
];
class _MyHomePageState extends State<MyHomePage> {
int _screen = 0;
#override
Widget build(BuildContext context) {
return new DefaultTabController(
length: tabNames.length,
child: new Scaffold(
appBar: new AppBar(
title: new Text('Navigation example'),
),
body: new TabBarView(
children: new List<Widget>.generate(tabNames.length, (int index) {
switch (_screen) {
case 0: return new Center(
child: new Text('First screen, ${tabNames[index]}'),
);
case 1: return new Center(
child: new Text('Second screen'),
);
}
}),
),
bottomNavigationBar: new Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
new AnimatedCrossFade(
firstChild: new Material(
color: Theme
.of(context)
.primaryColor,
child: new TabBar(
isScrollable: true,
tabs: new List.generate(tabNames.length, (index) {
return new Tab(text: tabNames[index].toUpperCase());
}),
),
),
secondChild: new Container(),
crossFadeState: _screen == 0
? CrossFadeState.showFirst
: CrossFadeState.showSecond,
duration: const Duration(milliseconds: 300),
),
new BottomNavigationBar(
currentIndex: _screen,
onTap: (int index) {
setState(() {
_screen = index;
});
},
items: [
new BottomNavigationBarItem(
icon: new Icon(Icons.airplanemode_active),
title: new Text('Airplane'),
),
new BottomNavigationBarItem(
icon: new Icon(Icons.motorcycle),
title: new Text('Motorcycle'),
),
],
),
],
),
),
);
}
}
Related
I have a pageview view and it works with sliding. But how do I integrate this back button as leading: Icon(backbutton), when navigating between forms in the pageview? Thanks
screen1.dart
import 'package:app/src/features/examples/components/body.dart';
class OnboardingExampleFlowPage extends StatelessWidget {
static String routeName = "/onboarding_example_flow";
const OnboardingExampleFlowPage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
extendBodyBehindAppBar: true,
appBar: AppBar(
elevation: 1,
backgroundColor: AppColors.monochromeWhite,
title: Text(context.l10n.buttonBack),
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () {},
),
),
body: const Body(),
);
}
}
Body has pageview:
body.dart
class _BodyState extends State<Body> {
int currentPage = 0;
final PageController controller = PageController();
#override
void dispose() {
super.dispose();
controller.dispose();
}
#override
Widget build(BuildContext context) {
final List<Widget> formPages = <Widget>[
ExampleContent01(controller: controller),
ExampleContent02(controller: controller),
ExampleContent03(controller: controller),
ExampleContent04(controller: controller),
];
return SafeArea(
child: SizedBox(
child: Column(
children: [
const SizedBox(height: 6),
AppStepper(
currentPage: currentPage,
length: formPages.length,
noSkip: true,
),
Expanded(
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: getProportionateScreenWidth(20),
),
child: PageView(
controller: controller,
onPageChanged: (value) => setState(() => currentPage = value),
children: formPages,
),
),
),
],
),
),
);
}
These forms: There are contents in ExampleScreens, but I did not add their code because there are AppBar and Pageview in the code I added.
here is view: want to be able to go back inside pageview.
Thanks a lot!
Just move the controller up, to the parent widget, so it's possible to navigate the pages with it.
Check out the live demo on DartPad.
The code is going to be like the following:
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const OnboardingExampleFlowPage(),
scrollBehavior: MyCustomScrollBehavior(),
debugShowCheckedModeBanner: false,
);
}
}
class OnboardingExampleFlowPage extends StatefulWidget {
static String routeName = "/onboarding_example_flow";
const OnboardingExampleFlowPage({Key? key}) : super(key: key);
#override
State<OnboardingExampleFlowPage> createState() =>
_OnboardingExampleFlowPageState();
}
class _OnboardingExampleFlowPageState extends State<OnboardingExampleFlowPage> {
final PageController controller = PageController();
#override
void dispose() {
controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
extendBodyBehindAppBar: true,
appBar: AppBar(
elevation: 1,
title: const Text('Back'),
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () {
controller.previousPage(
duration: const Duration(milliseconds: 250),
curve: Curves.easeOut,
);
},
),
),
body: Body(controller: controller),
);
}
}
class Body extends StatefulWidget {
const Body({super.key, required this.controller});
final PageController controller;
#override
State<Body> createState() => _BodyState();
}
class _BodyState extends State<Body> {
int currentPage = 0;
#override
Widget build(BuildContext context) {
const List<Widget> formPages = [
Center(child: Text('Page 1')),
Center(child: Text('Page 2')),
Center(child: Text('Page 3')),
Center(child: Text('Page 4')),
];
return SafeArea(
child: SizedBox(
child: Column(
children: [
const SizedBox(height: 6),
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: PageView(
controller: widget.controller,
onPageChanged: (value) => setState(() => currentPage = value),
children: formPages,
),
),
),
],
),
),
);
}
}
// Enables scrolling with mouse dragging
class MyCustomScrollBehavior extends MaterialScrollBehavior {
#override
Set<PointerDeviceKind> get dragDevices => {
PointerDeviceKind.touch,
PointerDeviceKind.mouse,
};
}
Dont have body widget in separate file
Put it in the _OnboardingExampleFlowPageState instead.
And it is the _OnboardingExampleFlowPageState that should have controller and
currentIndex variables.
So on leading button click you'll do something like this:
onPressed: () {
if (currentPage > 0) {
controller.previousPage(
duration: const Duration(milliseconds: 200),
curve: Curves.easeOut,
);
setState(() {
currentPage--;
});
}
},
Is it possible to change the TabBar indicator programmatically when swiping?
I've tried using a builder to get the index but I haven't had any luck .. I'm sure there must be a way to do this but haven't figured it out yet
Color _indicatorColor(index) {
switch (index) {
case 0:
return Colors.purple;
break;
case 1:
return colorInfoLighter;
break;
case 2:
return Colors.pink;
break;
}
}
Widget _buildScreen() {
var index;
return Scaffold(
appBar: AppBar(),
bottomNavigationBar: TabBar(
onTap: (_) {
setState(() {});
},
indicatorWeight: 4,
indicatorColor: _indicatorColor(index),
tabs: [
_requestedLabel(),
_completedLabel(),
_cancelledLabel(),
]),
body: Container(
child: TabBarView(children: [
_requestedTab(),
_completedTab(),
_cancelledTab(),
]),
),
);
}
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 3,
child: _buildScreen(),
);
}
Did you mean by changing tabs?
import 'dart:math';
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: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({
Key key,
}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
final colors = [Colors.purple, Colors.green, Colors.pink];
Color indicatorColor;
TabController _controller;
#override
void initState() {
super.initState();
_controller = TabController(length: 3, vsync: this)
..addListener(() {
setState(() {
indicatorColor = colors[_controller.index];
});
});
indicatorColor = colors[0];
}
Widget _buildScreen() {
return Scaffold(
appBar: AppBar(),
bottomNavigationBar: Container(
color: Colors.blue,
child: TabBar(
labelColor: Colors.black,
controller: _controller,
indicatorWeight: 4,
indicatorColor: indicatorColor,
tabs: [
Tab(
child: Container(
child: Text('A'),
),
),
Tab(
child: Text('B'),
),
Tab(
child: Text('C'),
),
]),
),
body: Container(
child: TabBarView(
controller: _controller,
children: [
Center(
child: Text('aa'),
),
Center(
child: Text('bb'),
),
Center(
child: Text('cc'),
),
],
),
),
);
}
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 3,
child: _buildScreen(),
);
}
}
I have a BottomNavigationBar that navigates to other pages when pressing an icon. This works fine, except the value of the currentIndex property in BottomNavigationBar doesn't update when the state updates, which means there is no change on the acual BottomNavigationBar. enter image description here
I'm using a vaiable (_selectedPage) to keep track of the selected index in the BottomNavigationBar, and the value changes when tapping an item, but it's not updating the currentIndex property when the state updates.. why is that?
import 'package:flutter/material.dart';
import 'package:independentproject/pages/home_page.dart';
import 'package:independentproject/pages/cook_recipe.dart';
class PageNavigationBar extends StatefulWidget {
#override
_PageNavigationBarState createState() => _PageNavigationBarState();
}
class _PageNavigationBarState extends State<PageNavigationBar> {
//default page showing in bottom navigation bar will be CookRecipe()
int _selectedPage = 1;
//all pages optional in bottom navigation bar
final List<Widget> _pageOptions = [
HomePage(),
CookRecipe(),
];
void onTapped(int pageTapped) {
setState(() {
//print(pageTapped);
_selectedPage = pageTapped;
Navigator.push(context, MaterialPageRoute(builder: (context) => _pageOptions[pageTapped]));
//print(_selectedPage);
});
}
#override
Widget build(BuildContext context) {
return BottomNavigationBar(
//TODO: currentIndex: doesn't update when the state updates, why?
currentIndex: _selectedPage,
//items showing in bottom navigation bar
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text('Homepage'),
),
BottomNavigationBarItem(
icon: Icon(Icons.search),
title: Text('Search recipe'),
),
],
onTap: (int pageTapped) {
onTapped(pageTapped);
},
);
}
}
import 'package:flutter/material.dart';
import 'package:independentproject/page_navigation_bar.dart';
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Home page'),
),
body: Center(
child: Text('Home page'),
),
bottomNavigationBar: PageNavigationBar(),
),
);
}
}
import 'package:flutter/material.dart';
import 'package:independentproject/page_navigation_bar.dart';
class CookRecipe extends StatefulWidget {
#override
_CookRecipeState createState() => _CookRecipeState();
}
class _CookRecipeState extends State<CookRecipe> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Search recipe'),
),
body: Center(
child: Text('Search recipes'),
),
bottomNavigationBar: PageNavigationBar(),
),
);
}
}
I would advise you to create a widget that will contain the BottomNavigationBar and also PageView that would allow you to switch pages with PageController.
For example:
class _MainScreenState extends State<MainScreen> {
PageController _pageController;
int _page = 1;
Duration pageChanging = Duration(milliseconds: 300);//this is for page animation-not necessary
Curve animationCurve = Curves.linear;//this is for page animation-not necessary
_MainScreenState();
#override
void initState() {
super.initState();
_pageController = PageController(initialPage: 1);
}
Widget build(BuildContext context) {
return Scaffold(
body: PageView(
physics: BouncingScrollPhysics(),
scrollDirection: Axis.horizontal,
controller: _pageController,
onPageChanged: onPageChanged,
children: <Widget>[
//here are all the pages you need:
//CookRecipe(),
],
),
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(
Icons.message,
),
title: Container(height: 0.0),
),
BottomNavigationBarItem(
icon: Icon(
Icons.home,
),
title: Container(height: 0.0),
),
BottomNavigationBarItem(
icon: Icon(
Icons.person,
),
title: Container(height: 0.0),
),
],
onTap: navigationTapped,
selectedItemColor: Theme.of(context).backgroundColor,
currentIndex: _page,
),
),
);
}
void navigationTapped(int page) {
_pageController.animateToPage(page,duration: pageChanging,
curve: animationCurve,);
}
#override
void dispose() {
super.dispose();
_pageController.dispose();
}
void onPageChanged(int page) {
if (this.mounted){
setState(() {
this._page = page;
});
}}
You can also do this without the PageView,and use only the controller to switch pages.
BTW-you create new instance of the navigation bar when you load a page which is bad practice
it is because PageNavigationBar is a own class, when you call there a setstate only this class updates
take a look at the Provider
a very usefull state management Package
or you can also handle your Page, when the NavBar is your Main Page and you have only one Page
return MaterialApp(
home: Scaffold(
appBar: ownAppBar(_selectedPage),
body: _bodyOptions[_selectedPage],
bottomNavigationBar: BottomNavigationBar(
currentIndex: _selectedPage,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text('Homepage'),
),
BottomNavigationBarItem(
icon: Icon(Icons.search),
title: Text('Search recipe'),
),
],
onTap: (int pageTapped) {
onTapped(pageTapped);
},
)
),
);
final List<Widget> _bodyOptions = [
HomePage(),
CookRecipe(),
];
You don't need to use Navigator to change pages, I modified your code just try.
import 'package:flutter/material.dart';
main() {
runApp(MaterialApp(home: PageNavigationBar()));
}
class PageNavigationBar extends StatefulWidget {
#override
_PageNavigationBarState createState() => _PageNavigationBarState();
}
class _PageNavigationBarState extends State<PageNavigationBar> {
//default page showing in bottom navigation bar will be CookRecipe()
int _selectedPage = 1;
//all pages optional in bottom navigation bar
final List<Widget> _pageOptions = [
HomePage(),
CookRecipe(),
];
void onTapped(int pageTapped) {
setState(() {
//print(pageTapped);
_selectedPage = pageTapped;
// Navigator.push(context, MaterialPageRoute(builder: (context) => _pageOptions[pageTapped]));
//print(_selectedPage);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: _pageOptions[_selectedPage],
bottomNavigationBar: BottomNavigationBar(
//TODO: currentIndex: doesn't update when the state updates, why?
currentIndex: _selectedPage,
//items showing in bottom navigation bar
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text('Homepage'),
),
BottomNavigationBarItem(
icon: Icon(Icons.search),
title: Text('Search recipe'),
),
],
onTap: (int pageTapped) {
onTapped(pageTapped);
},
),
);
}
}
class CookRecipe extends StatefulWidget {
#override
_CookRecipeState createState() => _CookRecipeState();
}
class _CookRecipeState extends State<CookRecipe> {
#override
Widget build(BuildContext context) {
return Center(
child: Text('Search recipes'),
);
}
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return Center(
child: Text('Home page'),
);
}
}
In my app I have two pages Page1 and Page2. I also have tab bar which is displayed at the bottom of the screen. The problem is that the TabBar goes away when I use Navigator.push from one of the pages. Check out the animations below:
Here is all my code:
void main() => runApp(App());
class App extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: "Hello",
home: DefaultTabController(
length: 2,
child: Scaffold(
bottomNavigationBar: TabBar(tabs: <Widget>[
Tab(icon: Icon(Icons.directions_car)),
Tab(icon: Icon(Icons.do_not_disturb))
],
labelColor: Colors.black
)
,
body: TabBarView(children: <Widget>[
Page1(),
Page2()
])
)
)
);
}
}
class Page1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Page 1'),
),
body: FlatButton(
child: Text('Go to Page 2'),
onPressed: () {
Navigator.push(context, MaterialPageRoute(
builder: (context) {
return Page2();
}
));
},
color: Colors.orange
)
);
}
}
class Page2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Page 2'),
),
body: FlatButton(
child: Text('Go to Page 1'),
onPressed: () {
Navigator.push(context, MaterialPageRoute(
builder: (context) {
return Page1();
}
));
},
color: Colors.purple
)
);
}
}
what you want can be easily done with the help of cupertino widgets.
Example Code:
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
void main() => runApp(MainPage());
class MainPage extends StatefulWidget {
#override
_MainPageState createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
int _currentIndex = 0;
#override
Widget build(BuildContext context) {
return CupertinoApp(
debugShowCheckedModeBanner: false,
title: 'Demo App',
home: CupertinoTabScaffold(
tabBar: CupertinoTabBar(
items: [
BottomNavigationBarItem(
icon: Icon(Icons.event), title: Text("Tab 1")),
BottomNavigationBarItem(
icon: Icon(Icons.group), title: Text("Tab 2")),
],
currentIndex: _currentIndex,
onTap: (int) {
setState(() {
_currentIndex = int;
});
},
),
tabBuilder: (context, int) {
switch (int) {
case 0:
{
return CupertinoTabView(
builder: (context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Text('Tab 1 Content'),
),
CupertinoButton.filled(
child: Text('Goto next Page in Tab1'),
onPressed: () {
Navigator.push(context,
CupertinoPageRoute(builder: (context) {
return Body(int);
}));
})
],
),
);
},
);
}
break;
case 1:
{
return CupertinoTabView(
builder: (context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Text('Tab 2 Content'),
),
CupertinoButton.filled(
child: Text('Goto next Page in Tab2'),
onPressed: () {
Navigator.push(context,
CupertinoPageRoute(builder: (context) {
return Body(int);
}));
})
],
),
);
},
);
}
break;
}
},
),
);
}
}
class Body extends StatefulWidget {
final int index;
Body(this.index);
#override
_BodyState createState() => _BodyState();
}
class _BodyState extends State<Body> {
#override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text('Page2 of Tab${widget.index}'),
),
child: Center(
child: Container(
child: Text('Page 2'),
),
));
}
}
EDIT
Sorry I misunderstood the question, this may be a duplicate of Flutter: Keep BottomNavigationBar When Push to New Screen with Navigator
Original answer
Use a single master page and replace the body dynamically with each sub page (containing their own content) :
Example :
import 'package:flutter/material.dart';
class HomePage extends StatefulWidget {
HomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
// current page index of the bottom navigation bar
int _currentIndex = 0;
// update the state of the index on tab tap
void onTabTapped(int index) {
setState(() {
_currentIndex = index;
});
}
#override
Widget build(BuildContext context) {
// list of pages of the bottom navigation bar
final List<Widget> _children = [
FirstPage(title: "My page 1"),
SecondPage(title: "My page 2"),
ThirdPage(title: "My page 3"),
];
return Scaffold(
backgroundColor: Colors.transparent,
appBar: AppBar(
title: Text(widget.title),
),
body: _children[_currentIndex],
bottomNavigationBar: BottomNavigationBar(
onTap: onTabTapped,
currentIndex: _currentIndex,
type: BottomNavigationBarType.shifting,
items: [
BottomNavigationBarItem(icon: Icon(Icons.event), title: Text("Page 1")),
BottomNavigationBarItem(icon: Icon(Icons.group), title: Text("Page 2")),
BottomNavigationBarItem(icon: Icon(Icons.camera_alt), title: Text("Page 3")),
],
),
);
}
}
Then FirstPage, SecondPage, ThirdPage can content only their own content :
import 'package:flutter/material.dart';
class FirstPage extends StatefulWidget {
FirstPage({Key key, this.title}) : super(key: key);
final String title;
#override
_FirstPageState createState() => _FirstPageState();
}
class _FirstPageState extends State<FirstPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: // your body content
);
}
}
Pushing a route will set the Widget as the child of the MaterialApp. Every screen should contain it's own scaffold with it's own BottonNavigatorBar.
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