I have a TabBarView(), and i need to show a MessageDialog (showDialog) asking if really want to leave this tab. is there any way to do it?
this is the body of my code
child: Scaffold(
drawer: SideMenu(),
appBar: AppBar(
title: Text("Antecedentes"),
bottom: TabBar(
isScrollable: true,
controller: _controller,
tabs: [
Tab(text: 'Tab # 1'),
Tab(text: 'Tab # 2'),
Tab(text: 'Tab # 3'),
),
),
body: TabBarView(
controller: _controller,
children: [
TabOnePage(),
TabTwoPage(),
TabThreePage(),
],
),
),
Im using version 2.2.3 of Flutter.
I appreciate help on this .
Show AlertDialog on Tabbar onTap action, and set TabBar index to previous one(this will allow TabBar to stay on the same tab):
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Tabbar Demo"),
bottom: TabBar(
onTap: (index) {
print(index);
showAlert(tabController.index);
tabController.index = tabController.previousIndex;
},
unselectedLabelColor: Colors.white,
labelColor: Colors.black,
tabs: [
Tab(icon: Icon(Icons.chat)),
Tab(icon: Icon(Icons.drafts)),
Tab(icon: Icon(Icons.ac_unit))
],
controller: tabController,
indicatorColor: Colors.black,
indicatorSize: TabBarIndicatorSize.tab,
),
),
body: TabBarView(
children: <Widget>[
CustomView("First"),
CustomView("Second"),
CustomView("Third"),
],
controller: tabController,
));
}
And upon selection of the "OK" button in the AlertDialog, set Tabbar index to the new one.
void showAlert(int newIndex) {
AlertDialog alertDialog = new AlertDialog(
content: new Container(
height: 80.0,
child: new Column(
children: <Widget>[
new Text("Want to leave this tab?"),
new RaisedButton(
child: new Text("OK"),
onPressed: () {
tabController.index = newIndex;
Navigator.pop(context);
},
)
],
),
),
);
showDialog(context: context, child: alertDialog);
}
Related
I am developing a flutter app, in home screen i have tabs( each tab is showing a category) and by click one of them the category products will appear.
Just like that
The problem is when i click home first i must have a general products from all categories and no category should be selected first.
After the user see's the general products he can then choose category he wants to see.
So i must customize the tabs and i don't know how.
Any idea?
Here is a demo widget using DefaultTabController, you can archive it easily.
class Home extends StatelessWidget {
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 4,
child: Scaffold(
body: NestedScrollView(
floatHeaderSlivers: true,
headerSliverBuilder: (context, innerBoxIsScrolled) => [
SliverAppBar(
snap: true,
floating: true,
toolbarHeight: 80,
backgroundColor: Colors.white,
title: Container(
width: double.infinity,
color: Colors.redAccent,
child: Text("search here"),
),
centerTitle: true,
bottom: PreferredSize(
preferredSize: Size(0.0, 48.0),
child: Column(
children: [
TabBar(
isScrollable: true,
indicatorWeight: 1,
labelColor: Colors.green,
unselectedLabelColor: Colors.grey,
// indicatorSize: TabBarIndicatorSize.label,
labelStyle: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16.0,
),
tabs: [
Tab(text: "screen1"),
Tab(text: "screen2"),
Tab(text: "screen3"),
Tab(text: "screen4"),
],
),
],
),
),
)
],
body: TabBarView(
children: [
Container(
child: Text("screen1"),
),
Container(
child: Text("screen2"),
),
Container(
child: Text("screen3"),
),
Container(
child: Text("screen4"),
),
],
)),
),
);
}
}
The Drawer work perfectly, but after I add tab bar in the main page. The navigator from drawer to other page get error 'noSuchMethodError: the method '*' was called on null'. I mean, when click the listTile from drawer. It lead to that error.
This is my code
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: getTitleFontColor(),
centerTitle: true,
title: appBarTitle,
),
drawer: new Drawer(
child:
_drawerLeft(context),
),
body:
new DefaultTabController(
length: 3,
child: new Scaffold(
appBar: new AppBar(
actions: <Widget>[],
title:
TabBar(
isScrollable: true,
unselectedLabelColor: Colors.white.withOpacity(0.3),
indicatorColor: Colors.white,
tabs: [
Tab(
child: Text('A'),
),
Tab(
child: Text('B'),
),
Tab(
child: Text('C'),
),
]
),
),
body: TabBarView(
children: <Widget>[
Container(
//A,
),
Container(
child: ListView(
children:<Widget>[
Column(children: <Widget>[
// B,
],)
])
),
Container(
child: ListView(
children:<Widget>[
Column(children: <Widget>[
// C
],)
])
),
],
),
)
),
// ),
);
}
My _drawerLeft()
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
ListTile(
leading: Icon(Icons.credit_card,color: getTitleFontColor()),
title: Text(
"A",
style: TextStyle(
color: getTitleFontColor(), fontSize: 16
)
),
onTap: () => {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => APage()),
),
},
),
])
Is it I use the navigator wrong? Can someone help please.
I am trying to show Snackbar on a Firebase Cloud Message event, not on the push of a button as most examples are showing.
I have a DefaultTabController like the one below. Where would I put my Snackbar in the tree to have the message display in any of the tabs?
#override
Widget build(BuildContext context) {
return DefaultTabController(
initialIndex: 1,
length: 3,
child: Scaffold(
appBar: AppBar(
backgroundColor: Colors.black,
flexibleSpace: new Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
new TabBar(
tabs: [
Tab(icon: Icon(Icons.person)),
Tab(icon: Icon(Icons.open)),
Tab(icon: Icon(Icons.people)),
],
),
],
),
),
body: TabBarView(physics: NeverScrollableScrollPhysics(), children: [
MyForm(),
MyWidget(),
MyOtherForm(),
]),
),
);
}
}
I believe that as long as it's below the Scaffold it doesn't matter where the call is done.
I'd basically like to have a TabView navigation in the middle of my page.
To do so I used a SliverAppBar inside a NestedScrollView.
My SliverAppBar is only composed by my TabView, I wrapped my TabView inside a SliverAppBar in order to used the pinned: true propriety.
return Scaffold(
appBar: AppBar(
title: Text('Title'),
),
body: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool boxIsScrolled) {
return <Widget>[
SliverToBoxAdapter(
child: Container(
height: 500,
color: Colors.red,
)),
SliverAppBar(
pinned: true,
bottom: TabBar(
tabs: <Widget>[
Tab(
text: "Home",
icon: Icon(Icons.home),
),
Tab(
text: "Example page",
icon: Icon(Icons.help),
)
],
controller: _tabController,
)),
];
},
body: TabBarView(
children: <Widget>[
PageExample(),
PageExample(),
],
controller: _tabController,
),
),
);
It does the trick, my problem is I'd like to hide/remove this SliverAppBar that wrapped my TabBar:
I needed to set expandedHeight to 0:
return Scaffold(
appBar: AppBar(
title: Text('Title'),
),
body: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool boxIsScrolled) {
return <Widget>[
SliverToBoxAdapter(
child: Container(
height: 500,
color: Colors.red,
)),
SliverAppBar(
expandedHeight: 0,
pinned: true,
bottom: TabBar(
tabs: <Widget>[
Tab(
text: "Home",
icon: Icon(Icons.home),
),
Tab(
text: "Example page",
icon: Icon(Icons.help),
)
],
controller: _tabController,
)),
];
},
body: TabBarView(
children: <Widget>[
PageExample(),
PageExample(),
],
controller: _tabController,
),
),
);
I wish to add the tab app instead of app bar on my home screen. How to create it. Currently, my tab bar added at the bottom of app bar and I have removed the title and elevation. At the same time, I can't say appBar: null as I need some space on the top of the tab bar.
Widget HomeTap = new Scaffold(
appBar: new AppBar(
bottom: new TabBar(
indicatorColor: Colors.pinkAccent[100],
labelColor: Colors.pinkAccent[100],
indicatorWeight: 0.5,
unselectedLabelColor: Colors.grey[400],
tabs: [
new Tab(text: 'Album',),
new Tab(text: 'Artist'),
new Tab(text: 'Playlist'),
new Tab(text: 'Songs'),
new Tab(icon: new Icon(Icons.search))
]),
title: null,
elevation: 0.0,
),
body: new TabBarView(
children: [
new Center(
child: new AlbumWidget(),
),
new Container(),
new Container(),
new Container(),
new Container(),
],
),
);
Flutter works with composition. You can pretty much replace any widget with something else. They are not limited to one specific child.
So you can simply do
new Scaffold(
appBar: new TabBar(
...
),
...
)
The only requirement is for your widget to be of the right interface.
Scaffold requires as appBar a PreferredSizeWidget.
Fortunately, TabBar is already a PreferredSizeWidget by default. So no change needed
#override
Widget build(BuildContext context) {
return MaterialApp(
home: DefaultTabController(
length: 3,
child: Scaffold(
appBar: AppBar(
title: Text('Tabs Demo'),
),
body:
Column(
children: <Widget>[
TabBar(
tabs: [
Tab(icon: Icon(Icons.directions_car)),
Tab(icon: Icon(Icons.directions_transit)),
Tab(icon: Icon(Icons.directions_bike)),
],
),
Expanded(
flex: 1,
child: TabBarView(
children: [
Icon(Icons.directions_car),
Icon(Icons.directions_transit),
Icon(Icons.directions_bike),
],
),
)
],
)
),
),
);
this worked for me
Tried flexibleSpace?
return DefaultTabController(
length: 3,
child: Scaffold(
appBar: AppBar(
flexibleSpace: new Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
TabBar(
tabs: [
Tab(text: "Pending"),
Tab(text: "Delivered"),
Tab(text: "Rejected"),
],
)
],
),
),
body: TabBarView(
children: [
PendingOrders(),
DeliveredOrders(),
RejectedOrders(),
],
),
),
);