Flutter How to vertically center the AppBar sliver tilte? - flutter

I'm trying to center the title of Sliver AppBar and add a second text below this. I can not do it.
Below is the image that is now and how it should be.
Can anyone help me?
This is my code.
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Slive AppBar',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
debugShowCheckedModeBanner: false,
home: new MyHomePage(title: 'Slive AppBar'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return new Scaffold(
drawer: new Drawer(),
body: new CustomScrollView(
scrollDirection: Axis.vertical,
slivers: <Widget>[
new SliverAppBar(
expandedHeight: 150.0,
flexibleSpace: const FlexibleSpaceBar(
title: const Text("US\$ 123.456.78"),
centerTitle: true,
),
backgroundColor: Colors.redAccent,
pinned: true,
actions: <Widget>[
new IconButton(
icon: const Icon(Icons.add_circle),
tooltip: 'Balance',
onPressed: () {/* ... */},
),
],
),
],
));
}
}
""
""
""
""""""
""
""""""""""
""
""
""""""""""""""""""""""""""""

You can create a Column widget with the children that you need:
return new Scaffold(
drawer: new Drawer(),
body: new CustomScrollView(
scrollDirection: Axis.vertical,
slivers: <Widget>[
new SliverAppBar(
expandedHeight: 140.0,
flexibleSpace: FlexibleSpaceBar(
title: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const Text("US\$ 123.456.78", textAlign: TextAlign.center,),
const Text("Anything", style: TextStyle(fontSize: 12.0),textAlign: TextAlign.center,),
],
),
centerTitle: true,
),
backgroundColor: Colors.redAccent,
pinned: true,
actions: <Widget>[
new IconButton(
icon: const Icon(Icons.add_circle),
tooltip: 'Balance',
onPressed: () {/* ... */},
),
],
),
],
));

Related

How can I replace appBar with SliverAppBar in my code?

class _HomepageState extends State<Homepage> {
int pageNum = 0;
final pages = [
TodayPage(), /*HistoryPage()*/
];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Today Medicine List'),
titleTextStyle: TextStyle(
fontSize: 30.0, fontWeight: FontWeight.w400, color: Colors.white),
elevation: 5.0,
),
body: pages[pageNum],
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.blueAccent,
onPressed: () {
Addingpage();
},
child: const Icon(CupertinoIcons.add)),
floatingActionButtonLocation: FloatingActionButtonLocation.endDocked,
bottomNavigationBar: ButtonBottomAppBar(),
);
}
This is code what I have. I want to replace appBar with SliverAppBar.
#override
Widget build(BuildContext context) {
return Scaffold(
// appBar: AppBar(
// title: Text('Today Medicine List'),
// titleTextStyle: TextStyle(
// fontSize: 30.0, fontWeight: FontWeight.w400, color: Colors.white),
// elevation: 5.0,
// ),
body: CustomScrollView(
slivers: [
SliverAppBar(
title: Text('Today Medicine List'),
floating: true,
flexibleSpace: Placeholder(),
expandedHeight: 200,
),
],
),
pages[pageNum],
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.blueAccent,
onPressed: () {
Addingpage();
},
child: const Icon(CupertinoIcons.add)),
floatingActionButtonLocation: FloatingActionButtonLocation.endDocked,
bottomNavigationBar: ButtonBottomAppBar(),
);
}
So I put CustomScrollView slivers code at body part, and page[pageNum] doesn't work properly.
How can I make it work both CustomScrollView() and page[pageNum] at one body:
The floatingActionButton is used with the Scaffold.
new Scaffold(
body: new CustomScrollView(
slivers: <Widget>[
new SliverAppBar(...),
...
],
),
floatingActionButton: new FloatingActionButton(...),
);
You can also use a Stack above the CustomScrollView and the FloatingActionButton (in a Positioned widget) as well.
Try replacing the SliverAppBar this way
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
const SliverAppBar(
pinned: true,
floating: true,
flexibleSpace: FlexibleSpaceBar(
title: Text('Today Medicine List'),
background: FlutterLogo(),
),
expandedHeight: 200,
),
SliverToBoxAdapter(
child: Container(
height: 500,
color: Colors.red,
child: pages[pageNum],
),
),
],
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.blueAccent,
onPressed: () {
Addingpage();
},
child: const Icon(CupertinoIcons.add),
),
floatingActionButtonLocation: FloatingActionButtonLocation.endDocked,
bottomNavigationBar: ButtonBottomAppBar(),
);
}
}

How do I allow gestures to pass through a widget in a stack?

please look at the code sample below, or just run it here
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) => MaterialApp(
home: Material(
child: Stack(
children: [
Center(
child: MaterialButton(
color: Colors.white,
child: Icon(Icons.ac_unit),
onPressed: () => print('pressed'),
),
),
CustomScrollWidget()
],
),
),
);
}
class CustomScrollWidget extends StatelessWidget {
#override
Widget build(BuildContext context) => CustomScrollView(
slivers: <Widget>[
SliverAppBar(
pinned: true,
expandedHeight: MediaQuery.of(context).size.height,
flexibleSpace: FlexibleSpaceBar(
title: const Center(child: Text('scroll me')),
),
),
const SliverFillRemaining(),
],
);
}
how do I allow gestures to pass through a widget in a stack?
AFAIK setting the HitTestBehavior of a GestureDetector only affect the child,
so shouldn't work in a Stack, any idea?
please note that the ""solutions"" (1, 2) offered here do not work
It's not a pretty solution but it does work:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) => MaterialApp(
home: Material(
child: Stack(
children: [
Center(
child: MaterialButton(
color: Colors.white,
child: Icon(Icons.ac_unit),
onPressed: () {},
),
),
CustomScrollWidget(),
Center(
child: MaterialButton(
elevation: 0.0,
hoverColor: Colors.transparent,
hoverElevation: 0.0,
onPressed: () => print('pressed'),
),
),
],
),
),
);
}
class CustomScrollWidget extends StatelessWidget {
#override
Widget build(BuildContext context) => CustomScrollView(
slivers: <Widget>[
SliverAppBar(
pinned: true,
expandedHeight: MediaQuery.of(context).size.height,
flexibleSpace: FlexibleSpaceBar(
title: const Center(child: Text('scroll me')),
),
),
const SliverFillRemaining(),
],
);
}

How to constrain ListTile in widget hierarchy

How can I make a ListTile work inside this widget hierarchy:
SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: [
Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Radio(
value: 1,
groupValue: 1,
onChanged: (sel) {},
),
GestureDetector(
child: Row(
children: <Widget>[
//Text('Title'), -- This is OK, but ListTile fails
ListTile(
title: Text('Title'),
subtitle: Text('Subtitle'),
),
],
),
onTap: () {},
),
],
),
],
),
),
Please understand that I am not in full control of the widget hierarchy -- a framework is building the SingleChildScrollView, Radio, GestureDetector, etc. I am simply trying to supply a child widget for an option. (I replicated the hierarchy in a simplified form to debug and experiment.)
I'm getting an exception:
flutter: ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
flutter: The following assertion was thrown during performLayout():
flutter: BoxConstraints forces an infinite width.
flutter: These invalid constraints were provided to RenderParagraph's layout() function by the following
flutter: function, which probably computed the invalid constraints in question:
flutter: _RenderListTile._layoutBox (package:flutter/src/material/list_tile.dart:1318:9)
flutter: The offending constraints were:
flutter: BoxConstraints(w=Infinity, 0.0<=h<=Infinity)
Normally when I encounter this kind of problem, I simply wrap the widget in an Expanded, but that is not working in this case.
Note that if I replace the ListTile with a simple Text widget, then it renders fine.
You can wrap the ListTile in a Container or a ConstrainedBox and set its maxWidth:
ConstrainedBox(
constraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width - 50,
),
child: ListTile(
title: Text('Title'),
subtitle: Text('Subtitle'),
trailing: Text('Trailing'),
),
),
You can copy paste run full code below
You can use IntrinsicWidth wrap Row and Expanded wrap ListTile and you can have more than one Expaned ListTile
GestureDetector(
child: IntrinsicWidth(
child: Row(
children: <Widget>[
//Text('Title'), -- This is OK, but ListTile fails
Expanded(
child: ListTile(
title: Text('Title'),
subtitle: Text('Subtitle'),
),
),
],
),
),
working demo
full code
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: 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> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: [
Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Radio(
value: 1,
groupValue: 1,
onChanged: (sel) {},
),
GestureDetector(
child: IntrinsicWidth(
child: Row(
children: <Widget>[
//Text('Title'), -- This is OK, but ListTile fails
Expanded(
child: ListTile(
isThreeLine: true,
title: Text('Title'),
subtitle: Text('this is long text this is long text this is long text \n'* 10),
),
),
],
),
),
onTap: () {},
),
],
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
full code 2 relayout
import 'package:flutter/cupertino.dart';
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: 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> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: [
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
flex: 1,
child: Radio(
value: 1,
groupValue: 1,
onChanged: (sel) {},
),
),
Expanded(
flex: 5,
child: GestureDetector(
child: LayoutBuilder(
builder:(context, constraints) {
print(constraints.maxWidth);
print(constraints.minWidth);
return ConstrainedBox(
constraints: BoxConstraints(
maxWidth: constraints.maxWidth),
child: ListTile(
//isThreeLine: true,
title: Text('Title'),
subtitle: Text(
'Textlargeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
overflow: TextOverflow.ellipsis,
maxLines: 2,
style: TextStyle(
fontSize: 13.0,
fontFamily: 'Roboto',
color: Color(0xFF212121),
fontWeight: FontWeight.bold,
),
),
),
);
}
),
onTap: () {},
),
),
],
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}

Hide the TabBar like a SliverAppBar

So there are many examples on the web where you can use a SliverAppBar that hides on scroll, and the TabBar below is still showing. I can't find anything that does it the other way around: When I scroll up I want to hide only the TabBar, keeping the AppBar persistent showing at all times. Does anyone know how to achieve this?
Here is a example with AppBar hiding (This is not what I want, just helps understand better what I want).
UPDATE
This is what I tried so far, and I thought it works, but the problem is I can't get the AppBar in the Positioned field to have the correct height (e.g. iPhone X its height is way bigger and overlaps with the tab bar).
// this sliver app bar is only use to hide/show the tabBar, the AppBar
// is invisible at all times. The to the user visible AppBar is below
return Scaffold(
body: Stack(
children: <Widget>[
NestedScrollView(
headerSliverBuilder:
(BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
floating: true,
snap: true,
pinned: false,
bottom: TabBar(
tabs: [
Tab(
child: Text(
"1",
textAlign: TextAlign.center,
),
),
Tab(
child: Text(
"2",
textAlign: TextAlign.center,
),
),
Tab(
child: Text(
"3",
textAlign: TextAlign.center,
),
),
],
controller: _tabController,
),
),
];
},
body: TabBarView(
children: [
MyScreen1(),
MyScreen2(),
MyScreen3(),
],
controller: _tabController,
physics: new NeverScrollableScrollPhysics(),
),
),
// Here is the AppBar the user actually sees. The SliverAppBar
// above will slide the TabBar underneath this one. However,
// I can´t figure out how to give it the correct height.
Container(
child: Positioned(
top: 0.0,
left: 0.0,
right: 0.0,
child: AppBar(
iconTheme: IconThemeData(
color: Colors.red, //change your color here
),
automaticallyImplyLeading: true,
elevation: 0,
title: Text("My Title"),
centerTitle: true,
),
),
),
],
),
);
Here is How you can do that, the idea is to use a postframecallback with the help of a GlobalKey to precalculate the appBar height and add an exapandedHeight like below,
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
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 {
TabController _tabController;
GlobalKey _appBarKey;
double _appBarHight;
#override
void initState() {
_appBarKey = GlobalKey();
_tabController = TabController(length: 3, vsync: this);
SchedulerBinding.instance.addPostFrameCallback(_calculateAppBarHeight);
super.initState();
}
_calculateAppBarHeight(_){
final RenderBox renderBoxRed = _appBarKey.currentContext.findRenderObject();
setState(() {
_appBarHight = renderBoxRed.size.height;
});
print("AppbarHieght = $_appBarHight");
}
#override
Widget build(BuildContext context) {
// this sliver app bar is only use to hide/show the tabBar, the AppBar
// is invisible at all times. The to the user visible AppBar is below
return Scaffold(
body: Stack(
children: <Widget>[
NestedScrollView(
headerSliverBuilder:
(BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
floating: true,
expandedHeight: _appBarHight,
snap: true,
pinned: false,
bottom: TabBar(
tabs: [
Tab(
child: Text(
"1",
textAlign: TextAlign.center,
),
),
Tab(
child: Text(
"2",
textAlign: TextAlign.center,
),
),
Tab(
child: Text(
"3",
textAlign: TextAlign.center,
),
),
],
controller: _tabController,
),
),
];
},
body: TabBarView(
children: [
MyScreen1(),
MyScreen2(),
MyScreen3(),
],
controller: _tabController,
physics: new NeverScrollableScrollPhysics(),
),
),
// Here is the AppBar the user actually sees. The SliverAppBar
// above will slide the TabBar underneath this one. However,
// I can¥t figure out how to give it the correct height.
Container(
key: _appBarKey,
child: Positioned(
top: 0.0,
left: 0.0,
right: 0.0,
child: AppBar(
backgroundColor: Colors.red,
iconTheme: IconThemeData(
color: Colors.red, //change your color here
),
automaticallyImplyLeading: true,
elevation: 0,
title: Text("My Title"),
centerTitle: true,
),
),
),
],
),
);
}
}
class MyScreen1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: Center(
child: Text("My Screen 1"),
),
);
}
}
class MyScreen2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: Center(
child: Text("My Screen 2"),
),
);
}
}
class MyScreen3 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: Center(
child: Text("My Screen 3"),
),
);
}
}
Edit:
After more investigation I found a solution without keys or MediaQuery "stuff" by using just SafeArea Widget . please check the following Complete code :
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
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 {
TabController _tabController;
#override
void initState() {
_tabController = TabController(length: 3, vsync: this);
super.initState();
}
#override
Widget build(BuildContext context) {
// this sliver app bar is only use to hide/show the tabBar, the AppBar
// is invisible at all times. The to the user visible AppBar is below
return Scaffold(
body: Stack(
children: <Widget>[
NestedScrollView(
headerSliverBuilder:
(BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
primary: true,
floating: true,
backgroundColor: Colors.blue,//.withOpacity(0.3),
snap: true,
pinned: false,
bottom: TabBar(
tabs: [
Tab(
child: Text(
"1",
textAlign: TextAlign.center,
),
),
Tab(
child: Text(
"2",
textAlign: TextAlign.center,
),
),
Tab(
child: Text(
"3",
textAlign: TextAlign.center,
),
),
],
controller: _tabController,
),
),
];
},
body: TabBarView(
children: [
MyScreen1(),
MyScreen2(),
MyScreen3(),
],
controller: _tabController,
physics: new NeverScrollableScrollPhysics(),
),
),
// Here is the AppBar the user actually sees. The SliverAppBar
// above will slide the TabBar underneath this one.
// by using SafeArea it will.
Positioned(
top: 0.0,
left: 0.0,
right: 0.0,
child: Container(
child: SafeArea(
top: false,
child: AppBar(
backgroundColor: Colors.blue,
// iconTheme: IconThemeData(
// color: Colors.red, //change your color here
// ),
automaticallyImplyLeading: true,
elevation: 0,
title: Text("My Title",),
centerTitle: true,
),
),
),
),
],
),
);
}
}
class MyScreen1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.yellow,
child: Center(
child: Text("My Screen 1"),
),
);
}
}
class MyScreen2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: Center(
child: Text("My Screen 2"),
),
);
}
}
class MyScreen3 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: Center(
child: Text("My Screen 3"),
),
);
}
}
Screenshot (Android)
Screenshot (iPhone X)
Your were very close, I have just modified couple of lines. I did it without using GlobalKey and other stuff (postFrameCallback etc). It is very simple and straightforward approach.
All you need to do is replace FlutterLogo with your own widgets which are MyScreen1, MyScreen2 and MyScreen3.
Code
void main() => runApp(MaterialApp(home: HomePage()));
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin {
TabController _tabController;
#override
void initState() {
super.initState();
_tabController = TabController(length: 3, vsync: this);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
floating: true,
snap: true,
pinned: true,
bottom: PreferredSize(
preferredSize: Size(0, kToolbarHeight),
child: TabBar(
controller: _tabController,
tabs: [
Tab(child: Text("1")),
Tab(child: Text("2")),
Tab(child: Text("3")),
],
),
),
),
];
},
body: TabBarView(
controller: _tabController,
children: [
FlutterLogo(size: 300, colors: Colors.blue), // use MyScreen1()
FlutterLogo(size: 300, colors: Colors.orange), // use MyScreen2()
FlutterLogo(size: 300, colors: Colors.red), // use MyScreen3()
],
physics: NeverScrollableScrollPhysics(),
),
),
Positioned(
top: 0.0,
left: 0.0,
right: 0.0,
child: MediaQuery.removePadding(
context: context,
removeBottom: true,
child: AppBar(
iconTheme: IconThemeData(color: Colors.red),
automaticallyImplyLeading: true,
elevation: 0,
title: Text("My Title"),
centerTitle: true,
),
),
),
],
),
);
}
}
I think its pretty easy using nested scaffolds. where you dont need to calculate any height. Just put the tabbar inside a SilverAppBar not below the SilverAppBar.
feel free to comment if that doesnt solve your problem.
Example:
return Scaffold(
appBar: AppBar(), //your appbar that doesnt need to hide
body: Scaffold(
appBar: SilverAppBar(
pinned: false,
floating: false,
flexibleSpace: new Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
new TabBar() //your tabbar that need to hide when scrolling
])
)
body: //your content goes here
)
);

Flutter: How to attach a FloatingActionButton to the AppBar?

The Scaffold-Widget only allows to place a FloatingActionButton at the bottom right or the bottom center. How can I place it between AppBar and body like here?
[
It is now possible using:
Scaffold(
appBar: AppBar(title: Text('Title'),),
body: ...,
floatingActionButtonLocation: FloatingActionButtonLocation.endTop,
floatingActionButton: FloatingActionButton(...),
),
Siva Kumar gave nice example, but the second have of the FAB was not clickable. So I made some changes in the code and it works great now!
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
double appBarHeight = 200.0;
#override
Widget build(BuildContext context) {
return new Stack(
children: <Widget>[
new Scaffold(
appBar: new PreferredSize(
preferredSize: new Size(MediaQuery.of(context).size.width, appBarHeight),
child: new Container(
color: Colors.blue,
child: new Container(
margin:const EdgeInsets.only(top: 30.0),
child: new Column(children: <Widget>[
new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new Row(
children: <Widget>[
new IconButton(
icon: new Icon(
Icons.arrow_back,
color: Colors.white,
),
onPressed: () {
Navigator.pop(context, false);
}
),
new Text(
"Controller Name",
style: new TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white
),
),
],
),
],
),
]
)
)
)
),
body: new Center(
child: new Text('Hello!'),
),
),
new Positioned(
child: new FloatingActionButton(
child: new Icon(Icons.add),
onPressed: () {
print('FAB tapped!');
},
backgroundColor: Colors.blueGrey,
),
right: 10.0,
top: appBarHeight - 5.0,
)
],
);
}
}
we can Achieve it by using stack
and code snippet look like this
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
import 'dart:io';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new PreferredSize(
preferredSize: new Size(MediaQuery.of(context).size.width, 200.0),
child:
new Stack(
alignment: const FractionalOffset(0.98, 1.12),
children: <Widget>[new Container(
color: Colors.blue,
child: new Column(
children: <Widget>[
new Container(
margin: const EdgeInsets.fromLTRB(0.0, 20.0, 0.0, 0.0),
child: new Column(children: <Widget>[
new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new Row(
children: <Widget>[
new IconButton(
icon: new Icon(
Icons.arrow_back,
color: Colors.white,
),
onPressed: () {
Navigator.pop(context, false);
}),
new Text(
"Controller Name",
style: new TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white),
),
],
),
],
),
]))
],
)
),new FloatingActionButton(onPressed: (){print("floating button Tapped");},child: new Icon(Icons.add),)],)
),
body: new Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child:
new Container(),
),
);
}
[![output][1]][1]}
for me the solution was, set floatingActionButtonLocation to FloatingActionButtonLocation.endTop
Scaffold(
floatingActionButtonLocation: FloatingActionButtonLocation.endTop)