Reputation: 1231
Following is my code where I am trying to navigate to the next tab from bottom navigation bar button. See mock for understanding.
Code:
class TabbedAppBarSample extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: DefaultTabController(
length: choices.length,
child: Scaffold(
floatingActionButtonLocation:
FloatingActionButtonLocation.centerDocked,
bottomNavigationBar: BottomAppBar(
notchMargin: 20,
child: new Row(
// mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Text(
'Next >',
style: TextStyle(fontSize: 20, color: Colors.red),
)
],
),
),
backgroundColor: Colors.white,
appBar: AppBar(
backgroundColor: Colors.white, // status bar color
brightness: Brightness.light,
title: TimerPage(),
bottom: TabBar(
// isScrollable: true,
indicatorColor: Colors.red,
unselectedLabelColor: Colors.grey,
labelColor: Colors.red,
tabs: choices.map((Choice choice) {
return Tab(
text: choice.title,
);
}).toList(),
),
),
body: TabBarView(
children: choices.map((Choice choice) {
return Padding(
padding: const EdgeInsets.all(6.0),
child: ChoiceCard(choice: choice),
);
}).toList(),
),
),
),
);
}
}
Mock:
Also, Idea is to navigate either via swipe or clicking on the Next button.
Upvotes: 3
Views: 4341
Reputation: 6646
The swiping behavior should already be there, but if you want to make a Text clickable like a button, you should look into some examples at How can I implement OnPressed callback for Text widget, Flutter. (I’ll use a FlatButton
in my example)
Second, I recommend doing this with a StatefulWidget
. Now, if you want a “next” button, then you’ll have to implement your own TabController
. In your button’s onPressed
, you can implement your “next” behavior by using TabController.animateTo()
. Simplified stateful example:
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
TabController myTabController;
@override
void initState() {
super.initState();
myTabController = new TabController(
vsync: this,
length: //your_choices,
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: BottomAppBar(
child: new Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
FlatButton(
onPressed: () {
myTabController.animateTo(myTabController.index + 1);
},
child: new Text('Next >'),
),
],
),
),
appBar: AppBar(
title: Text(widget.title),
bottom: TabBar(
controller: myTabController,
tabs: //your_choices,
),
),
body: TabBarView(
controller: myTabController,
children: //your_choices,
),
);
}
}
Now, if you want to keep it as StatelessWidget
. You’ll need to wrap your Scaffold
inside Builder
to access your DefaultTabController
for the same actions as above. Here’s a simplified example snippet of your Widget build(BuildContext context)
:
home: DefaultTabController(
length: //your_choices,
child: Builder(builder: (BuildContext context) {
return Scaffold(
bottomNavigationBar: BottomAppBar(
child: new Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
FlatButton(
onPressed: () {
DefaultTabController.of(context).animateTo(DefaultTabController.of(context).index + 1);
},
child: new Text('Next >'),
),
],
),
),
appBar: ...
body: ...
);
}),
)
Modify as needed.
Upvotes: 3
Reputation: 54367
With TabController and animateTo
You can see full code below
code snippet
@override
void initState() {
super.initState();
_tabController = TabController(vsync: this, length: 3);
}
void _toggleTab() {
_tabIndex = _tabController.index + 1;
_tabController.animateTo(_tabIndex);
}
...
bottomNavigationBar: BottomAppBar(
notchMargin: 20,
child: new Row(
// mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
InkWell(
onTap: () {
_toggleTab();
},
working demo
full code
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
final appTitle = 'Tabs Demo';
return MaterialApp(
title: appTitle,
home: MyHomePage(title: appTitle),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
const MyHomePage({Key key, this.title}) : super(key: key);
@override
State<StatefulWidget> createState() {
return _MyHomePageState();
}
}
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
int _tabIndex = 0;
TabController _tabController;
@override
void initState() {
super.initState();
_tabController = TabController(vsync: this, length: 3);
}
void _toggleTab() {
_tabIndex = _tabController.index + 1;
_tabController.animateTo(_tabIndex);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
bottomNavigationBar: BottomAppBar(
notchMargin: 20,
child: new Row(
// mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
InkWell(
onTap: () {
_toggleTab();
},
child: Text(
'Next >',
style: TextStyle(fontSize: 20, color: Colors.red),
),
)
],
),
),
appBar: AppBar(
title: Text(widget.title),
bottom: TabBar(
controller: _tabController,
tabs: [
Tab(text: 'Tab 1'),
Tab(text: 'Tab 2'),
Tab(text: 'Tab 3'),
],
),
),
body: TabBarView(
controller: _tabController,
children: [
Card(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTile(
leading: Icon(Icons.album),
title: Text('Hello 1'),
subtitle: Text('Click on Next Button to go to Tab 2.'),
),
],
),
),
Card(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTile(
leading: Icon(Icons.album),
title: Text('Hello 2'),
subtitle: Text('Click on Next Button to go to Tab 3'),
),
],
),
),
Card(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTile(
leading: Icon(Icons.album),
title: Text('Hello 3'),
subtitle: Text('The End'),
),
],
),
),
],
),
));
}
}
Upvotes: 3