How can I replace appBar with SliverAppBar in my code? - flutter

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(),
);
}
}

Related

Receiving an error in my flutter code. The named parameter 'child' isn't defined

I am reciving an error with my flutter app.
Here is the error
Error: No named parameter with the name 'child' in Flutter
The error is on line 51 and 62
Im trying to build an app in flutter. Im reciving an error when using child. Im trying to make an elevated button and some text but for both im reciving this error
Here is my code:
import 'package:flutter/material.dart';
import 'package:audioplayers/audioplayers.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Time Attack',
theme: ThemeData(
primarySwatch: Colors.red,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
backgroundColor: Colors.red,
title: const Text('Time Attack'),
centerTitle: true,
),
floatingActionButton: FloatingActionButton(
onPressed: () {
final player = AudioCache();
//player.play('musicForapp.mp3');
},
backgroundColor: Colors.red,
child: const Icon(Icons.punch_clock),
),
body: Column(
child: Container(
color: Colors.red,
child: const Text(
"Click the Icon in the bottem left to simulate an alarm",
style: TextStyle(
color: Colors.white,
fontSize: 30.0,
),
),
),
),
child: ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => const TasksPage(),
),
);
}, //on pressed
child: const Text("Navigate"),
),
),
);
} //widget build
} //_MyHomePageState
class TasksPage extends StatefulWidget {
const TasksPage({super.key});
#override
State<TasksPage> createState() => _TasksPageState();
}
class _TasksPageState extends State<TasksPage> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
backgroundColor: Colors.red,
title: const Text('Tasks'),
centerTitle: true,
),
body: const Center(
child: Text(
"What is 2 x 2?",
style: TextStyle(
color: Colors.white,
fontSize: 30.0,
),
),
),
),
);
} //widget build
} //_TasksPageState
Why am I reciving this error?
that is because Column should have a children, not a child. try this
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
backgroundColor: Colors.red,
title: const Text('Time Attack'),
centerTitle: true,
),
floatingActionButton: FloatingActionButton(
onPressed: () {
final player = AudioCache();
//player.play('musicForapp.mp3');
},
backgroundColor: Colors.red,
child: const Icon(Icons.punch_clock),
),
body: Column(
children: [
Container(
color: Colors.red,
child: const Text(
"Click the Icon in the bottem left to simulate an alarm",
style: TextStyle(
color: Colors.white,
fontSize: 30.0,
),
),
),
ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => const TasksPage(),
),
);
}, //on pressed
child: const Text("Navigate"),
)
],
),
),
);
} //widget build
} /

Tabbar Customisation in Flutter

I have studied about creating Tabbar in Flutter but as so far I know We can create Tabbar inside AppBar widget which is inside Scaffold widget.
But I want something like below :
So far I have as below:
I have created Tab screens but have to manage tab selections as above.
As you can see above, Appbar is different and tabbar is outside Appbar,
How can I manage this to customise this Tabs in Flutter? Thanks.
try this
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
const MyHomePage({
Key? key,
required this.title,
}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 3,
child: Scaffold(
appBar: AppBar(
centerTitle: false,
title: Text(
"Facilities",
style: TextStyle(color: Colors.black, fontSize: 20),
),
actions: <Widget>[
Padding(
padding: EdgeInsets.only(right: 20.0),
child: GestureDetector(
onTap: () {},
child: Icon(
Icons.search,
size: 26.0,
),
)),
],
backgroundColor: Colors.white,
elevation: 0,
bottom: TabBar(
unselectedLabelColor: Colors.redAccent,
indicatorSize: TabBarIndicatorSize.tab,
indicator: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.redAccent, Colors.orangeAccent]),
borderRadius: BorderRadius.circular(6),
color: Colors.redAccent),
tabs: [
Tab(
child: Align(
alignment: Alignment.center,
child: Text("Attraction"),
),
),
Tab(
child: Align(
alignment: Alignment.center,
child: Text("Events"),
),
),
Tab(
child: Align(
alignment: Alignment.center,
child: Text("Utils"),
),
),
]),
),
body: TabBarView(children: [
Icon(Icons.apps),
Icon(Icons.movie),
Icon(Icons.games),
]),
));
}
}

In flutter,How to add a button at the bottom and top of ListView

How to add a button,this button bottom of screen and top of listview?
like this
You can just do it using 'Stack' widget.
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> {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: _buildBody(),
);
}
Widget _buildBody() {
return Stack(
children: <Widget>[
ListView.builder(
itemCount: 50,
itemBuilder: (context, index) {
return Container(
height: 30,
padding: EdgeInsets.symmetric(horizontal: 20),
child: Text('$index'),
);
},
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
margin: EdgeInsets.symmetric(horizontal: 20, vertical: 40),
width: double.infinity,
child: FlatButton(
child: Text('FlatButton', style: TextStyle(fontSize: 24)),
onPressed: () => {},
color: Colors.green,
textColor: Colors.white,
),
),
),
],
);
}
}

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 vertically center the AppBar sliver tilte?

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: () {/* ... */},
),
],
),
],
));