Related
I have a ListView in which I will dynamically add in some children of same type. Inside every children widget has a button. What I want to implement is, that, when user presses the button on a child widget, this child widget will be removed from the ListView. I can do this in C# using events, but I'm a total noob to Dart and Flutter.
Here is my ListView
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text('Edit Plan'),
backgroundColor: Colors.green,
actions: <Widget>[
Builder(
builder: (context) => IconButton(
icon: Icon(Icons.add),
onPressed: () {
setState(() {
txts.add('set');
});
},
),
)
],
),
backgroundColor: Colors.white,
body: ListView(
children: txts.map((string) =>
new ListViewItem()).toList(growable: false),
),
);
}
And here is my listViewItem:
class ListViewItem extends StatelessWidget {
final Workout workout;
ListViewItem({Key key, #required this.workout})
: assert(workout != null),
super(key: key);
#override
Widget build(BuildContext context) {
// TODO: implement build
final theme = Theme.of(context);
return Padding(
padding: EdgeInsets.all(12),
child: Card(
elevation: 12,
color: Colors.green,
child: Padding(
padding: EdgeInsets.only(top: 4, bottom: 4, left: 8, right: 8),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const ListTile(
leading: Icon(Icons.album),
title: Text(
'The Enchanted Nightingale',
style: TextStyle(color: Colors.white),
),
subtitle: Text(
'Music by Julie Gable. Lyrics by Sidney Stein.',
style: TextStyle(color: Colors.white),
),
),
TextFormField(
decoration: InputDecoration(
labelText: 'Name your workout',
labelStyle: TextStyle(color: Colors.white)),
),
ButtonTheme.bar(
// make buttons use the appropriate styles for cards
child: ButtonBar(
children: <Widget>[
FlatButton(
child: const Text(
'DELETE',
style: TextStyle(color: Colors.white),
),
onPressed: () {},
),
],
),
),
],
),
)),
);
}
}
I edited your code to use a ListView.builder, you need to remove the item at index from the List (txts) you are using, your code will be as follows:
List<String> txts = List();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Edit Plan'),
backgroundColor: Colors.green,
actions: <Widget>[
Builder(
builder: (context) =>
IconButton(
icon: Icon(Icons.add),
onPressed: () {
setState(() {
txts.add('set');
});
},
),
)
],
),
backgroundColor: Colors.white,
body: new ListView.builder(
itemCount: txts.length,
itemBuilder: (BuildContext context, int index) {
return ListViewItem(
workout: workout,
onDelete: (){
setState(() {
txts.removeAt(index);
});
},
);
},
),
);
}
in addition to that you need to add an ondelete callback in the ListViewItem, the code in the ListViewItem class will be as follows:
class ListViewItem extends StatelessWidget {
final Workout workout;
final VoidCallback onDelete;
ListViewItem({Key key, #required this.workout, this.onDelete})
: assert(workout != null),
super(key: key);
#override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Padding(
padding: EdgeInsets.all(12),
child: Card(
elevation: 12,
color: Colors.green,
child: Padding(
padding: EdgeInsets.only(top: 4, bottom: 4, left: 8, right: 8),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const ListTile(
leading: Icon(Icons.album),
title: Text(
'The Enchanted Nightingale',
style: TextStyle(color: Colors.white),
),
subtitle: Text(
'Music by Julie Gable. Lyrics by Sidney Stein.',
style: TextStyle(color: Colors.white),
),
),
TextFormField(
decoration: InputDecoration(
labelText: 'Name your workout',
labelStyle: TextStyle(color: Colors.white)),
),
ButtonTheme.bar(
// make buttons use the appropriate styles for cards
child: ButtonBar(
children: <Widget>[
FlatButton(
child: const Text(
'DELETE',
style: TextStyle(color: Colors.white),
),
onPressed: () =>onDelete(),
),
],
),
),
],
),
)),
);
}
}
I have a dot indicator in bottom of the page. I need to hide this after 5 seconds sliding to bottom. When user move to other page show dots sliding to top and finally after 5 seconds hide again. Now the dots hide after 5 seconds in fade out but i need other type of animation.
import 'package:flutter/material.dart';
import 'package:iGota/screens/partials/dots_indicator.dart';
import 'package:iGota/screens/posts_page.dart';
import 'package:iGota/screens/maps_page.dart';
class HomePage extends StatefulWidget {
static String tag = 'home-page';
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<HomePage> {
final _controller = new PageController();
static const _kDuration = const Duration(milliseconds: 300);
static const _kCurve = Curves.ease;
final _kArrowColor = Colors.black.withOpacity(0.8);
bool _visible = true;
void initState() {
super.initState();
Future.delayed(Duration(milliseconds: 5)).then((_) => _visible = !_visible);
}
#override
Widget build(BuildContext context) {
final List<Widget> _pages = <Widget>[
new ConstrainedBox(
constraints: const BoxConstraints.expand(),
child: new FlatButton(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FlatButton(
onPressed: () {
Navigator.pushNamed(context, PostsPage.tag);
},
child: Column(
children: <Widget>[
IconButton(
icon:
Icon(Icons.save_alt, color: Colors.white, size: 30.0),
onPressed: () {
Navigator.pushNamed(context, PostsPage.tag);
},
),
Text(
"Contenedores",
style: TextStyle(color: Colors.white, fontSize: 20.0),
)
],
),
),
],
),
splashColor: Colors.white,
color: Colors.blue[300],
onPressed: () {
Navigator.pushNamed(context, PostsPage.tag);
},
),
),
new ConstrainedBox(
constraints: const BoxConstraints.expand(),
child: new FlatButton(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FlatButton(
onPressed: () {
Navigator.pushNamed(context, MapsPage.tag);
},
child: Column(
children: <Widget>[
IconButton(
icon: Icon(Icons.bubble_chart,
color: Colors.white, size: 30.0),
onPressed: () {
Navigator.pushNamed(context, MapsPage.tag);
},
),
Text(
"Válvulas",
style: TextStyle(color: Colors.white, fontSize: 20.0),
)
],
),
),
],
),
splashColor: Colors.white,
color: Colors.red[300],
onPressed: () {
Navigator.pushNamed(context, MapsPage.tag);
},
),
),
];
return new Scaffold(
body: new IconTheme(
data: new IconThemeData(color: _kArrowColor),
child: new Stack(
children: <Widget>[
new PageView.builder(
physics: new AlwaysScrollableScrollPhysics(),
controller: _controller,
itemCount: _pages.length,
itemBuilder: (BuildContext context, int index) {
this._visible=true;
return _pages[index % _pages.length];
},
),
new Positioned(
bottom: 0.0,
left: 0.0,
right: 0.0,
child: AnimatedOpacity(
opacity: _visible ? 1.0 : 0.0,
duration: Duration(milliseconds: 3000),
child: new Container(
color: Colors.grey[800].withOpacity(0.5),
padding: const EdgeInsets.all(20.0),
child: new Center(
child: new DotsIndicator(
controller: _controller,
itemCount: _pages.length,
onPageSelected: (int page) {
_controller.animateToPage(
page,
duration: _kDuration,
curve: _kCurve,
);
},
),
),
),
),
)
],
),
),
);
}
}
I think position transition would help me but i don't know exactly how can i add to my code without rewriting. So anybody can help me?
UPDATE
import 'package:flutter/material.dart';
import 'package:iGota/screens/partials/dots_indicator.dart';
import 'package:iGota/screens/posts_page.dart';
import 'package:iGota/screens/maps_page.dart';
class HomePage extends StatefulWidget {
static String tag = 'home-page';
#override
HomePageState createState() => new HomePageState();
}
class HomePageState extends State<HomePage>
with SingleTickerProviderStateMixin {
final _controller = new PageController();
static const _kDuration = const Duration(milliseconds: 300);
static const _kCurve = Curves.ease;
final _kArrowColor = Colors.black.withOpacity(0.8);
AnimationController controller;
Animation<Offset> offset;
#override
void initState() {
super.initState();
controller =AnimationController(vsync: this, duration: Duration(seconds: 1));
Future.delayed(Duration(seconds: 5)).then((_) => controller.forward());
offset = Tween<Offset>(begin: Offset.zero, end: Offset(0.0, 1.0))
.animate(controller);
}
#override
Widget build(BuildContext context) {
GestureDetector(onTap: () {
setState(() {
controller.reverse();
});
});
final List<Widget> _pages = <Widget>[
new ConstrainedBox(
constraints: const BoxConstraints.expand(),
child: new FlatButton(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FlatButton(
onPressed: () {
Navigator.pushNamed(context, PostsPage.tag);
},
child: Column(
children: <Widget>[
IconButton(
icon:
Icon(Icons.save_alt, color: Colors.white, size: 30.0),
onPressed: () {
Navigator.pushNamed(context, PostsPage.tag);
},
),
Text(
"Contenedores",
style: TextStyle(color: Colors.white, fontSize: 20.0),
)
],
),
),
],
),
splashColor: Colors.white,
color: Colors.blue[300],
onPressed: () {
Navigator.pushNamed(context, PostsPage.tag);
},
),
),
new ConstrainedBox(
constraints: const BoxConstraints.expand(),
child: new FlatButton(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FlatButton(
onPressed: () {
Navigator.pushNamed(context, MapsPage.tag);
},
child: Column(
children: <Widget>[
IconButton(
icon: Icon(Icons.bubble_chart,
color: Colors.white, size: 30.0),
onPressed: () {
Navigator.pushNamed(context, MapsPage.tag);
},
),
Text(
"Válvulas",
style: TextStyle(color: Colors.white, fontSize: 20.0),
)
],
),
),
],
),
splashColor: Colors.white,
color: Colors.red[300],
onPressed: () {
Navigator.pushNamed(context, MapsPage.tag);
},
),
),
];
return new Scaffold(
body: new IconTheme(
data: new IconThemeData(color: _kArrowColor),
child: new Stack(
children: <Widget>[
new PageView.builder(
physics: new AlwaysScrollableScrollPhysics(),
controller: _controller,
itemCount: _pages.length,
itemBuilder: (BuildContext context, int index) {
return _pages[index % _pages.length];
},
),
new Positioned(
bottom: 0.0,
left: 0.0,
right: 0.0,
child: SlideTransition(
position: offset,
child: new Container(
color: Colors.grey[800].withOpacity(0.5),
padding: const EdgeInsets.all(20.0),
child: new Center(
child: new DotsIndicator(
controller: _controller,
itemCount: _pages.length,
onPageSelected: (int page) {
_controller.animateToPage(
page,
duration: _kDuration,
curve: _kCurve,
);
},
),
),
),
),
)
],
),
),
);
}
}
Now i need to call controller.reverse when user touch screen...
To create a sliding animation for your indicator (if I've understood your requirement right), I would simply suggest using the SlideTransition widget. It should not require much work to integrate it in your existing code.
The code belows shows a minimal example of the SlideTransition. If you'd like to keep displaying it during the navigation from one screen to another, you'd have to draw it in a layer above your Navigator.
If you do not like to use a Stack, you can instead use the Overlay functionality of flutter, as given in this answer. This would also solve the struggle, with keeping the animation displayed during the navigation transition.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Home(),
);
}
}
class Home extends StatefulWidget {
#override
State<StatefulWidget> createState() => HomeState();
}
class HomeState extends State<Home> with SingleTickerProviderStateMixin {
AnimationController controller;
Animation<Offset> offset;
#override
void initState() {
super.initState();
controller =
AnimationController(vsync: this, duration: Duration(seconds: 1));
offset = Tween<Offset>(begin: Offset.zero, end: Offset(0.0, 1.0))
.animate(controller);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
Center(
child: RaisedButton(
child: Text('Show / Hide'),
onPressed: () {
switch (controller.status) {
case AnimationStatus.completed:
controller.reverse();
break;
case AnimationStatus.dismissed:
controller.forward();
break;
default:
}
},
),
),
Align(
alignment: Alignment.bottomCenter,
child: SlideTransition(
position: offset,
child: Padding(
padding: EdgeInsets.all(50.0),
child: CircularProgressIndicator(),
),
),
)
],
),
);
}
}
I'm a beginner trying to practice coding with Flutter so it would be helpful if the explanation or suggestion is easy to understand. :) Thanks in advance!
[Goal]
I've created a two folders and one of them is for parts that can be used in multiple places without having to create them every time. And the other one includes files with different pages (I like to keep them separate).
[Question]
I'm currently trying to navigate by using the side drawer and want to go to other pages, however it's not working and I'm getting blanks in black :( Please help...
In this case, should I use the "routes:" argument or should I use the MaterialPageRoute() or is there something else that can be suggested?
I apologize for posting the entire code, but I thought it would be best to understand the whole context. If there's anything that seems odd or have a better idea. Please do let me know!
[Code of Drawer]
class AppDrawer extends StatefulWidget {
#override
_AppDrawerState createState() => _AppDrawerState();
}
class _AppDrawerState extends State<AppDrawer> {
#override
Widget build(BuildContext context) {
return Drawer(
child: ListView(
children: <Widget>[
UserAccountsDrawerHeader(
accountName: Text('John T.'),
accountEmail: Text('*********#gmail.com'),
currentAccountPicture: GestureDetector(
child: CircleAvatar(
backgroundColor: Colors.grey,
child: Icon(Icons.person, color: Colors.white))),
decoration: BoxDecoration(color: Colors.red)),
ListTile(
leading: Icon(Icons.home, color: Colors.redAccent),
title: Text('Home'),
trailing: null,
onTap: () {
Navigator.of(context).pop();
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) {
Home();
},
),
);
},
),
ListTile(
leading: Icon(Icons.person, color: Colors.redAccent),
title: Text('My Acount'),
trailing: null,
onTap: () {
Navigator.of(context).pop();
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) {
MyAccount();
},
),
);
},
),
ListTile(
leading: Icon(Icons.fitness_center, color: Colors.redAccent),
title: Text('My Workout'),
trailing: null,
onTap: () {},
),
ListTile(
leading: Icon(Icons.cancel, color: Colors.redAccent),
title: Text('My Nutrition'),
trailing: null,
onTap: () {},
),
Divider(color: Colors.red, indent: 20.0),
ListTile(
leading: Icon(Icons.settings, color: Colors.blue),
title: Text('Settings'),
trailing: null,
onTap: () {},
),
ListTile(
leading: Icon(Icons.help, color: Colors.green),
title: Text('About'),
trailing: null,
onTap: () {},
),
],
),
);
}
}
[Code of Home Page]
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 5.0,
title: Text('Home'),
backgroundColor: Colors.red,
centerTitle: true,
),
endDrawer: AppDrawer(),
body: Container(
color: Colors.white,
child: Center(
child: ListView(
children: <Widget>[],
),
),
),
);
}
}
[My Account Page]
class MyAccount extends StatefulWidget {
final String value;
MyAccount({Key key, this.value}) : super (key: key);
#override
_MyAccountState createState() => _MyAccountState();
}
class _MyAccountState extends State<MyAccount> {
final TextEditingController _ageFieldController = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('My Account'),
centerTitle: true,
backgroundColor: Colors.blue,
),
endDrawer: AppDrawer(),
body: Container(
color: Colors.white,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
child: Column(
children: <Widget>[
TextField(
controller: _ageFieldController,
decoration: InputDecoration(
hintText: 'Example: 27',
),
autocorrect: true,
keyboardType: TextInputType.number,
),
Text('${widget.value}')
],
),
),
],
),
),
),
);
}
}
[Code of Main.dart]
void main(List<String> args) {
runApp(Bmi());
}
class Bmi extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'BMI',
theme: ThemeData(
primarySwatch: Colors.deepPurple,
),
home: Home(),
);
}
}
The Material Design guidelines suggest a Drawer for navigation between sites of equal importance, so Navigator.push() should not be used, because the animation it does looks like it's a linear navigation(like going to the next page, not one of equal importance.)
Here's a link regarding this topic: material.io site for Navigation Drawer Component
I always update my body according to the currently selected item in the drawer, similar as you would do it with a BottomNavigationBar.
An implementation of that would look similar to this:
return Scaffold(
drawer: Drawer(),
body: Stack(
children: <Widget>[
Offstage(
offstage: index != 0,
child: _buildAccountPage(),
),
Offstage(
offstage: index != 0,
child: _buildHomePage(),
),
],
),
);
You need to return New Page to the Builder Function of Navigator.
Correct Code:
ListTile(
leading: Icon(Icons.person, color: Colors.redAccent),
title: Text('My Acount'),
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => MyAccount()));
},
),
TextFormField is not working properly, its blinking continuously and it doesn't allow me to write anything, as I tap on the TextFormField my keyboard appears for a second and disappear instantly. I am confused what wrong I have done with my code, I've matched my code with previous working code, but still getting this behaviour .
Here is my code.
class ComingSoonState extends State<ComingSoon> {
String language;
TextEditingController _textEdititingController ;
#override
void initState() {
_textEdititingController = new TextEditingController(); //Initialised TextEditingController
super.initState();
}
#override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final Size size = MediaQuery.of(context).size;
final formData = new Form(
key: widget._formKey,
child: new Container(
padding: const EdgeInsets.only(
left: 35.0,
right: 35.0),
child: new Column(
children: <Widget>[
new Theme(
data: theme.copyWith(primaryColor: Colors.black54),
child: new TextFormField(
controller: _textEdititingController, //ADDED CONTROLLER HERE
style: const TextStyle(color: Colors.black54),
decoration: new InputDecoration(
labelText: 'Amount',
labelStyle: const TextStyle(color: Colors.black54)
),
// validator: this._validateEmail,
validator: (val) {
return val.isEmpty
? "Please enter amount"
: null;
},
onSaved: (String value) {
// this._data.email = value;
this.language = value;
}
),
),
],
),
),
);
return Scaffold(
appBar: new AppBar(
leading: null,
title: const Text('Send Money', style: const TextStyle(
color: Colors.white
),
),
),
body: new Container(
color: Colors.grey[300],
child: new ListView(
children: <Widget>[
new Container(
child: new Column(
children: <Widget>[
new Container(
height: 60.0 ,
padding: const EdgeInsets.all(5.0),
child: new Card(
child: new Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: new Text("Available balance in wallet", style:
new TextStyle(color: Colors.black54,
fontSize: 16.0
),),
),
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: new Text("123 KSH", style:
new TextStyle(color: Colors.blueAccent,
fontSize: 16.0
),),
),
],
),
),
) ,
new Container(
//height: 300.0,
padding: const EdgeInsets.all(5.0),
child: new Card(
child: new Container(
child: new Center(
child: new Column(
children: <Widget>[
formData
],
),
),
),
),
)
],
)
),
],
),
),
);
}
}
I added a floating action button that presents a dialog that will show what you entered into the TextField (using the controller). I'm not sure what form key you were passing in before but making the GlobalKey instance a member variable eliminates the keyboard present/dismiss issue.
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(title: 'Flutter Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String language;
TextEditingController _textEditingController;
final _formKey = GlobalKey<FormState>();
#override
void initState() {
_textEditingController =
TextEditingController(); //Initialised TextEditingController
super.initState();
}
#override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final Size size = MediaQuery.of(context).size;
final formData = Form(
key: _formKey,
child: Container(
padding: const EdgeInsets.only(left: 35.0, right: 35.0),
child: Column(
children: <Widget>[
Theme(
data: theme.copyWith(primaryColor: Colors.black54),
child: TextFormField(
controller: _textEditingController,
//ADDED CONTROLLER HERE
style: const TextStyle(color: Colors.black54),
decoration: InputDecoration(
labelText: 'Amount',
labelStyle: const TextStyle(color: Colors.black54)),
// validator: this._validateEmail,
validator: (val) {
return val.isEmpty ? "Please enter amount" : null;
},
onSaved: (String value) {
// this._data.email = value;
language = value;
}),
),
],
),
),
);
return Scaffold(
appBar: AppBar(
leading: null,
title: const Text(
'Send Money',
style: const TextStyle(color: Colors.white),
),
),
body: Container(
color: Colors.grey[300],
child: ListView(
children: <Widget>[
Container(
child: Column(
children: <Widget>[
Container(
height: 60.0,
padding: const EdgeInsets.all(5.0),
child: Card(
child: Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Text(
"Available balance in wallet",
style: TextStyle(
color: Colors.black54, fontSize: 16.0),
),
),
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Text(
"123 KSH",
style: TextStyle(
color: Colors.blueAccent, fontSize: 16.0),
),
),
],
),
),
),
Container(
//height: 300.0,
padding: const EdgeInsets.all(5.0),
child: Card(
child: Container(
child: Center(
child: Column(
children: <Widget>[formData],
),
),
),
),
)
],
)),
],
),
),
floatingActionButton: FloatingActionButton(
// When the user presses the button, show an alert dialog with the
// text the user has typed into our text field.
onPressed: () {
return showDialog(
context: context,
builder: (context) {
return AlertDialog(
// Retrieve the text the user has typed in using our
// TextEditingController
content: Text(_textEditingController.text),
);
},
);
},
tooltip: 'Show me the value!',
child: Icon(Icons.text_fields),
),
);
}
}
I've noticed that Drawer of Scaffold.drawer only shows up when an AppBar of Scaffold is present.
But Instead of AppBar,I Used BottomAppBar present in BottomNavigationBar.
How do I get Drawer working with BottomAppBar?
Here's my code Below for which Drawer dosen't appear
class homieclass extends State<homie>{
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: new Scaffold(
backgroundColor: Colors.white70.withOpacity(0.9),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: FloatingActionButton(onPressed: (){},backgroundColor: Colors.redAccent,child: ImageIcon(new AssetImage("ast/hello123.png")),),
bottomNavigationBar: BottomAppBar(child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,mainAxisSize: MainAxisSize.max,children: <Widget>[
IconButton(icon: Icon(Icons.menu), onPressed: (){}),IconButton(icon: Icon(Icons.message), onPressed: (){}),
],
),
),
body: new Column(
children: <Widget>[new SizedBox(height: 50.0, ),
Container(margin: EdgeInsets.only(left: 0.0),child: new Text("Events",textAlign: TextAlign.left,style: TextStyle(fontFamily: 'ssfr',fontSize: 35.0,fontWeight: FontWeight.bold),),)
, Container(margin: EdgeInsets.only(left: 10.0,right: 10.0) ,width: 360.0,height: 40.0,decoration: new BoxDecoration(color: Colors.blueGrey.withOpacity(0.2),
border: new Border.all(color: Colors.blueGrey.withOpacity(0.0), width: 2.0),
borderRadius: new BorderRadius.circular(10.0),),child: new Row(children: <Widget>[SizedBox(width: 10.0,),Icon(Icons.search,color: Colors.blueGrey.withOpacity(0.9),),Text(" Search",style: TextStyle(fontFamily: 'ssft',color: Colors.blueGrey,fontSize: 20.0),)],),)
,new SizedBox(height: 10.0,),new SizedBox(
height: 5.0,
child: new Center(
child: new Container(
margin: new EdgeInsetsDirectional.only(start: 1.0, end: 1.0),
height: 2.0
,
color: Colors.redAccent.withOpacity(0.8),
),
),
),],
),drawer: new Drawer(
child: new ListView(
children: <Widget>[ListTile(title: Text("hello"),)],
),
),
),
);
}
It works perfectly for me. Here is a working example with a dedicated "Show Drawer" button in the bottom bar (the drawer can also be dragged in from the left):
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Playground',
home: TestPage(),
);
}
}
class TestPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text('Body'),
),
bottomNavigationBar: Builder(builder: (BuildContext context) {
return BottomAppBar(
color: Colors.orange,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
IconButton(icon: Icon(Icons.menu), onPressed: () {
Scaffold.of(context).openDrawer();;
}),
IconButton(icon: Icon(Icons.message), onPressed: () {}),
],
),
);
},),
drawer: Drawer(
child: SafeArea(
right: false,
child: Center(
child: Text('Drawer content'),
),
),
),
);
}
}
Flutter version: Latest master build (though I'm also quite sure that it works with the beta version)
You can use Drawer, but you must supply a DrawerController, and also arrange for the drawer to overlay your other content. This is easy to do with a Stack. Its important that the stack hold a non-transparent container, otherwise you'll get rendering artifacts when the draw slides in and out. Scaffold doesn't require this, however, annoyingly, it also rebuild the other content as the draw moves (exactly the type of thing they've tried to avoid).
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutterui/util/layout_util.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) =>
MaterialApp(title: 'Flutter Playground',
home: Material(child:DrawerStack(body: body(), drawer: _drawer())));
}
Drawer _drawer() =>Drawer(
child: SafeArea(
child: Center(
child: Column(
children: [
Text('endDrawer content'),
Builder(builder:(context) => RaisedButton(
child: Text('Click', semanticsLabel: 'Click 2'),
onPressed: () {
Navigator.pop(context);
},
)),
],
),
),
),
);
Widget body() => Container(
decoration: BoxDecoration(color: Color.fromARGB(255, 255, 255, 255)),
child: SafeArea(
child: Center(
child: Column(children: [
Text('Body'), // style:TextStyle(fontSize: 14.0,color: Colors.black)),
Builder(builder:(context) => RaisedButton(
child: Text('Open drawer'),
onPressed: () {
(context.ancestorWidgetOfExactType(DrawerStack) as DrawerStack).openDrawer();
// DrawerStack.of(context).openDrawer();
})),
]))));
class DrawerStack extends StatelessWidget {
final GlobalKey<DrawerControllerState> _drawerKey =
GlobalKey<DrawerControllerState>();
final drawerScrimColor = Color.fromARGB(90, 100, 100, 128);
final double drawerEdgeDragWidth = null;
final DragStartBehavior drawerDragStartBehavior = DragStartBehavior.start;
final Widget body;
final Drawer drawer;
DrawerStack({Key key, this.body, this.drawer}) : super(key: key);
void openDrawer() {
_drawerKey.currentState?.open();
}
#override
Widget build(BuildContext context) => Stack(
children: [
// body
body,
DrawerController(
key: _drawerKey,
alignment: DrawerAlignment.end,
child: drawer,
drawerCallback: (_){},
dragStartBehavior: drawerDragStartBehavior,
//widget.drawerDragStartBehavior,
scrimColor: drawerScrimColor,
edgeDragWidth: drawerEdgeDragWidth,
),
],
);
}
You can openDrawer of global key from the flutter itself to do the job.
Scaffold.of(context).openDrawer() / Scaffold.of(context).openEndDrawer();
scaffoldKey.currentState.openDrawer(); / scaffoldKey.currentState..openEndDrawer();
Case 1
bottomNavigationBar:BottomAppBar(
elevation: 10,
shape: CircularNotchedRectangle(),
child: Container(
height: 80,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Expanded(
child: GestureDetector(
onTap: () {
Scaffold.of(context).openDrawer();
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.dashboard),
Text(
'DASHBOARD',
style: TextStyle(color: Colors.black),
),
],
),
),
),
Expanded(
child: GestureDetector(
onTap: () {},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.home),
Text(
'CHALLENGES',
style: TextStyle(color: Colors.black),
),
],
),
),
),
Expanded(
child: GestureDetector(
onTap: (){},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.public),
Text(
'Public',
style: TextStyle(color: Colors.black),
),
],
),
),
),
Expanded(
child: GestureDetector(
onTap: () {},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.sentiment_satisfied),
Text(
'Settings',
style: TextStyle(color: Colors.black),
),
],
),
),
),
],
),
),
color: AppColors.WHITE,
);
Case 2
or you can scaffold key
class BottomBar {
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
Widget build(BuildContext context) {
return Scaffold(
key: scaffoldKey,
bottomNavigationBar: BottomAppBar(
elevation: 10,
shape: CircularNotchedRectangle(),
child: Container(
height: 80,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Expanded(
child: GestureDetector(
onTap: () {
scaffoldKey.currentState.openDrawer();
// scaffoldKey.currentState.openEndDrawer(); // use to open end drawer
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.dashboard),
Text(
'DASHBOARD',
style: TextStyle(color: Colors.black),
),
],
),
),
),
Expanded(
child: GestureDetector(
onTap: () {},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.home),
Text(
'CHALLENGES',
style: TextStyle(color: Colors.black),
),
],
),
),
),
Expanded(
child: GestureDetector(
onTap: () {},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.public),
Text(
'Public',
style: TextStyle(color: Colors.black),
),
],
),
),
),
Expanded(
child: GestureDetector(
onTap: () {},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.sentiment_satisfied),
Text(
'Settings',
style: TextStyle(color: Colors.black),
),
],
),
),
),
],
),
),
color: AppColors.WHITE,
));
}
}