I've created a flutter app where I'm managing array for todolist in app. I've can add the text by add button.
I've created a widget to show in list.
My question is how am i supposed manage the UI of individual.
Code:
import 'package:flutter/material.dart';
class TodoList extends StatefulWidget {
_TodoListState createState() => new _TodoListState();
}
class _TodoListState extends State<TodoList> {
List _list = new List();
Widget listTile({String data: '[Empty data]'}) {
bool _writable = false;
TextEditingController _textController = new TextEditingController(text: data);
String _text = _textController.text;
if(!_writable){
return new Row(
children: <Widget>[
new Expanded(
child: new Text(data)
),
new IconButton(icon: new Icon(Icons.edit),
onPressed: () {
// setState(() {
_writable = ! _writable;
print(_writable.toString());
// });
}),
new IconButton(icon: new Icon(Icons.remove_circle), onPressed: null),
],
);
} else {
return new Row(
children: <Widget>[
new Expanded(
child: new TextField( controller: _textController )
),
new IconButton(icon: new Icon(Icons.done), onPressed: null),
],
);
}
}
void addInList(String string) {
print(string);
setState(() {
_list.add(string);
});
print(_list);
}
void removeFromList(int index){
}
static final TextEditingController _textController = new TextEditingController();
String get _text => _textController.text;
#override
Widget build(BuildContext context) {
Widget adderTile = new Row(
children: <Widget>[
new Expanded(
child:
new TextField(
textAlign: TextAlign.center,
controller: _textController ,
decoration: new InputDecoration( hintText: 'New item.!' ),
),
),
new IconButton(icon: new Icon(Icons.add), onPressed: (){addInList(_text);}),
],
);
return new MaterialApp(
title: 'TodoList',
home: new Scaffold(
appBar: new AppBar(title: new Text('TodoList'),),
body: new Column(
children: <Widget>[
adderTile,
new ListView.builder(
shrinkWrap: true,
itemCount: _list.length,
itemBuilder: (context, int index){
return listTile(data: _list[index]);
}
),
],
),
),
);
}
}
if i change _writable inside setState then it rerenders widget and _writable becomes false again. if i do it without setState, then _writable becomes true but widget doesn't rerender.
P.S.: i don't want to add another array in to manage which is writable and which is not. Thanks in advance.
The variable
bool _writable = false;
is declared as local variable in the method listTile(), but should be moved next to List _list = new List(); to become a member variable. Then use setState() to set it and rebuild the view.
Edit:
You should create a dedicated StatefulWidget (TodoListEntry), having _writable as member as suggested above. Move almost the whole method body of listTile(...) to the build()-method of the TodoListEntryState, make the parameter String data also a member and pass the value via the constructor.
Related
I am getting dirty state exception when redirecting on a new page after login. On this home page I am getting info from preferences.
class Home extends StatefulWidget{
#override
State<StatefulWidget> createState() => new _HomeState();
}
class _HomeState extends State<Home> {
Drawer drawer = new Drawer();
String strName, strEmail, strImageURL;
int userId;
Image imgProfile;
#override
void initState() {
super.initState();
_loadSharedPref();
}
//Loading Shared value on start
_loadSharedPref() async {
print('In Shared Profile');
try{
SharedPreferences prefs = await SharedPreferences.getInstance();
strName = prefs.getString('name');
print('Shared Profile Name '+strName);
setState(() {
strName = prefs.getString('name');
userId = prefs.getInt('userId');
strEmail = prefs.getString('email');
strImageURL = prefs.getString('avatar');
imgProfile = Image.network(Config.PROFILE_PIC+strImageURL);
print('Image URL ---- '+Config.PROFILE_PIC+strImageURL);
});
}catch(exception){
print('SharedProfile '+exception);
}
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: new Scaffold(
backgroundColor: whiteColor,
drawer: sideDrawer(),
appBar: new AppBar(
title: new Text('Test Page'),
),
),
);
}
//Profile Details
Widget profileDetail() {
return new DrawerHeader(
child: new Column(
children: <Widget>[
new CircleAvatar(
radius: 40,
backgroundColor : blueColor,
backgroundImage: new NetworkImage(Config.PROFILE_PIC+strImageURL),
),
],
)
);
}
//Side Drawer
Widget sideDrawer(){
return new Drawer(
child: new ListView(
children: <Widget>[
new Center(
child: profileDetail(),
),
new ListTile(
leading: new Icon(Icons.lightbulb_outline),
title: new Text('Requests'),
// onTap: () => _onListTileTap(context),
),
new ListTile(
leading: new Icon(Icons.lightbulb_outline),
title: new Text('Reviews'),
// onTap: () => _onListTileTap(context),
),
new ListTile(
leading: new Icon(Icons.lightbulb_outline),
title: new Text('Setting'),
// onTap: () => _onListTileTap(context),
),
new ListTile(
leading: new Icon(Icons.lightbulb_outline),
title: new Text('Tip'),
// onTap: () => _onListTileTap(context),
),
new ListTile(
leading: new Icon(Icons.lightbulb_outline),
title: new Text('Conditions'),
// onTap: () => _onListTileTap(context),
),
new ListTile(
leading: new Icon(Icons.lightbulb_outline),
title: new Text('About Us'),
// onTap: () => _onListTileTap(context),
),
new ListTile(
leading: new Icon(Icons.lightbulb_outline),
title: new Text('Log Out'),
// onTap: () => _onListTileTap(context),
),
],
),
);
}
}
Cross-link https://github.com/flutter/flutter/issues/25428
I went into the same kind of problem. Checking my variables having shared pref values for null or not worked for me.
Try checking strName, userId, strEmail, strImageURL, imgProfile are not null before using them in the widget.
if(strImageURL != null)
{
print('filepaths: '+strImageURL);
}
Try this out
//Profile Details
Widget profileDetail() {
return new DrawerHeader(
child: new Column(
children: <Widget>[
new CircleAvatar(
radius: 40,
backgroundColor : blueColor,
backgroundImage: strImageURL ?? AssetImage('some static file path') : NetworkImage(Config.PROFILE_PIC+strImageURL),
),
],
)
);
}
You probably didn't fill "name", "userId", "avatar" or "email" fields in your preferences and you are getting this error when trying to get with SharedPreferences.
just create statement everytime you trying to call the data from sharedPreference like this
body: yourDatainsharedPreference != null ?
//do something
:
// do something
I'm new to Flutter,
I want to destruct cards created initially and construct them again as per data provided in API call.
Basically when I tap on button in UI, it should call APIs and based on data from API call, if it is different from the data I already have, I want to destruct cards and construct them again.
How I can achieve this?
The cards will auto update their content when you make the call again, it is like refreshing your data.
I have made a simple example with a single card that shows data from this JSON Where I am calling the API first time in initState and then repeating the call each time I press on the FAB.
I am adding the index variable just to show you the updates (updating my single card with the next item in the list)
Also it is worth noting that I am handling the null or empty values poorly for the sake of time.
Also forget about the UI overflow ¯_(ツ)_/¯
class CardListExample extends StatefulWidget {
#override
_CardListExampleState createState() => new _CardListExampleState();
}
class _CardListExampleState extends State<CardListExample> {
Map cardList = {};
int index = 0;
#override
void initState() {
_getRequests();
super.initState();
}
_getRequests() async {
String url = "https://jsonplaceholder.typicode.com/users";
var httpClinet = createHttpClient();
var response = await httpClinet.get(
url,
);
var data = JSON.decode(response.body);
//print (data);
setState(() {
this.cardList = data[index];
this.index++;
});
print(cardList);
print(cardList["name"]);
}
#override
Widget build(BuildContext context) {
return new Scaffold(
floatingActionButton:
new FloatingActionButton(onPressed: () => _getRequests()),
appBar: new AppBar(
title: new Text("Card List Example"),
),
body: this.cardList != {}
? new ListView(children: <Widget>[
new Card(
child: new Column(
children: <Widget>[
new Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Text(
cardList["name"] ?? '',
style: Theme.of(context).textTheme.display1,
),
new Text(
this.cardList['email'] ?? '',
maxLines: 50,
),
],
),
new Text(cardList["website"] ?? '')
],
),
),
])
: new Center(child: new CircularProgressIndicator()),
);
}
}
Yes, Answer from Aziza works.
Though I used the code as below :
void main() =>
runApp(new MaterialApp(
onGenerateRoute: (RouteSettings settings) {
switch (settings.name) {
case '/about':
return new FromRightToLeft(
builder: (_) => new _aboutPage.About(),
settings: settings,
);
}
},
home : new HomePage(),
theme: new ThemeData(
fontFamily: 'Poppins',
primarySwatch: Colors.blue,
),
));
class HomePage extends StatefulWidget{
#override
HomePageState createState() => new HomePageState();
}
class HomePageState extends State<HomePage>{
List data;
Future<String> getData() async{
var response = await http.get(
Uri.encodeFull(<SOMEURL>),
headers: {
"Accept" : "application/json"
}
);
this.setState((){
data = JSON.decode(response.body);
});
return "Success";
}
#override
void initState() {
// TODO: implement initState
super.initState();
this.getData();
}
#override
Widget build(BuildContext context){
return new Scaffold(
appBar : new AppBar(
title : new Text("ABC API"),
actions: <Widget>[
new IconButton( // action button
icon: new Icon(Icons.cached),
onPressed: () => getData(),
)],
),
drawer: new Drawer(
child: new ListView(
children: <Widget> [
new Container(
height: 120.0,
child: new DrawerHeader(
padding: new EdgeInsets.all(0.0),
decoration: new BoxDecoration(
color: new Color(0xFFECEFF1),
),
child: new Center(
child: new FlutterLogo(
colors: Colors.blueGrey,
size: 54.0,
),
),
),
),
new ListTile(
leading: new Icon(Icons.chat),
title: new Text('Support'),
onTap: () {
Navigator.pop(context);
Navigator.of(context).pushNamed('/support');
}
),
new ListTile(
leading: new Icon(Icons.info),
title: new Text('About'),
onTap: () {
Navigator.pop(context);
Navigator.of(context).pushNamed('/about');
}
),
new Divider(),
new ListTile(
leading: new Icon(Icons.exit_to_app),
title: new Text('Sign Out'),
onTap: () {
Navigator.pop(context);
}
),
],
)
),
body: this.data != null ?
new ListView.builder(
itemCount: data.length,
itemBuilder: (BuildContext context, int index){
return new Container(
padding: new EdgeInsets.fromLTRB(8.0,5.0,8.0,0.0),
child: new Card(
child: new Padding(
padding: new EdgeInsets.fromLTRB(10.0,12.0,8.0,0.0),
child: new Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new ListTile(
enabled: data[index]['active'] == '1' ? true : false,
title: new Text(data[index]['header'],
style:Theme.of(context).textTheme.headline,
),
subtitle: new Text("\n" + data[index]['description']),
),
new ButtonTheme.bar(
child: new ButtonBar(
children: <Widget>[
new FlatButton(
child: new Text(data[index]['action1']),
onPressed: data[index]['active'] == '1' ? _launchURL :null,
),
],
),
),
],
),
),
),
);
},
)
:new Center(child: new CircularProgressIndicator()),
);
}
}
_launchURL() async {
const url = 'http://archive.org';
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
}
class FromRightToLeft<T> extends MaterialPageRoute<T> {
FromRightToLeft({ WidgetBuilder builder, RouteSettings settings })
: super(builder: builder, settings: settings);
#override
Widget buildTransitions(
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
if (settings.isInitialRoute)
return child;
return new SlideTransition(
child: new Container(
decoration: new BoxDecoration(
boxShadow: [
new BoxShadow(
color: Colors.black26,
blurRadius: 25.0,
)
]
),
child: child,
),
position: new Tween(
begin: const Offset(1.0, 0.0),
end: const Offset(0.0, 0.0),
)
.animate(
new CurvedAnimation(
parent: animation,
curve: Curves.fastOutSlowIn,
)
),
);
}
#override Duration get transitionDuration => const Duration(milliseconds: 400);
}
The above code includes Navigation drawer, page navigation animation and also answer to the above question.
Can someone fire up a quick flutter project and replace main.dart with the following and see what I'm doing wrong? I'm trying to get drag and drop working in ListView.
I'm not even sure this is the right approach so if not, please let me know.
The error I'm getting now is:
Another exception was thrown: 'package:flutter/src/rendering/box.dart': Failed assertion: line 1446 pos 12: 'hasSize': is not true.
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
final title = 'Basic List';
var tile1 = new Material(child:
new ListTile(
leading: new Icon(Icons.photo),
title: new Text('Row 1'),
trailing: new Icon(Icons.reorder),
));
var tile2 = new Material(
child:
new ListTile(
leading: new Icon(Icons.photo),
title: new Text('Row 2'),
trailing: new Icon(Icons.reorder),
));
return new MaterialApp(
title: title,
home: new Scaffold(
appBar: new AppBar(
title: new Text(title),
),
body:
new GestureDetector(
onVerticalDragStart: startDrag,
onVerticalDragEnd: endDrag,
child: new ListView(
shrinkWrap: true,
children: [
new Flex (
children: <Widget>[
new Flexible(
child: new Draggable(child: tile1, feedback:
tile1),
),
new Flexible(
child: new Draggable(child: tile2, feedback:
tile2),
),
],
direction: Axis.vertical,
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
),
],
),
),
),
);
}
void startDrag(DragStartDetails event) {}
void endDrag(DragEndDetails event) {}
}
Thanks
With a little help along the way from #Darky to resolve the issue hasSize issue, here's the finished sortable ListView example:
https://github.com/marchampson/FluterSortableListView
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatefulWidget {
#override
MyAppState createState() => new MyAppState();
}
class MyAppState extends State<MyApp> {
List<String> rows = new List<String>()
..add('Row 1')
..add('Row 2')
..add('Row 3')
..add('Row 4');
void _handleAccept(int data, int index) {
setState(() {
String imageToMove = rows[data];
rows.removeAt(data);
rows.insert(index, imageToMove);
});
}
#override
Widget build(BuildContext context) {
final title = 'Sortable ListView';
return new MaterialApp(
title: title,
home: new Scaffold(
appBar: new AppBar(
title: new Text(title),
),
body:
new LayoutBuilder(builder: (context, constraint) {
return new ListView.builder(
itemCount: rows.length,
addRepaintBoundaries: true,
itemBuilder: (context, index) {
return new LongPressDraggable(
key: new ObjectKey(index),
data: index,
child: new DragTarget<int>(
onAccept: (int data) {
_handleAccept(data, index);
},
builder: (BuildContext context, List<int> data, List<dynamic> rejects) {
return new Card(
child: new Column(
children: <Widget>[
new ListTile(
leading: new Icon(Icons.photo),
title: new Text(rows[index])
),
],
)
);
},
onLeave: (int data) {
// Debug
print('$data is Leaving row $index');
},
onWillAccept: (int data) {
// Debug
print('$index will accept row $data');
return true;
},
),
onDragStarted: () {
Scaffold.of(context).showSnackBar(new SnackBar (
content: new Text("Drag the row onto another row to change places"),
));
},
onDragCompleted: () {
print("Finished");
},
feedback: new SizedBox(
width: constraint.maxWidth,
child: new Card (
child: new Column(
children: <Widget>[
new ListTile(
leading: new Icon(Icons.photo),
title: new Text(rows[index]),
trailing: new Icon(Icons.reorder),
),
],
),
elevation: 18.0,
)
),
childWhenDragging: new Container(),
);
},
);
}),
),
);
}
}
I am trying to solve form validation in my app. Every time I click to TextFromField, the focus is lost and keyboard hide. I found that problem is with "_formKey". But I need it to validation. How to solve it?
code snippet:
class _TodoCreateDetailPageState extends State<TodoPage> {
#override
Widget build(BuildContext context) {
final GlobalKey<FormState> _formKey = new GlobalKey<FormState>();
String _title = widget.todo == null ? "New TODO" : widget.todo.title;
String _message;
return new Scaffold(
appBar: new AppBar(
title: new Text(_title),
),
floatingActionButton: new FloatingActionButton(
child: new Icon(Icons.save), onPressed: null),
body: new Padding(
padding: new EdgeInsets.all(20.0),
child: new Form(
key: _formKey,
child: new Column(
children: <Widget>[
new TextField(
decoration: new InputDecoration(labelText: 'Title'),
onChanged: (String value) {
_title = value;
},
),
new TextField(
decoration: new InputDecoration(labelText: 'Message'),
onChanged: (String value) {
_message = value;
},
)
],
))),
);
}
Change StatelessWidget to StatefulWidget works for me, as Derek Lakin said in comments.
this issue is due to GlobalKey Initialization with in build()
#override
Widget build(BuildContext context){
//here is the reason of losing focus.
final GlobalKey<FormState> _formKey = new GlobalKey<FormState>()
}
Remove it from build and you are all good.
final GlobalKey<FormState> _formKey = new GlobalKey<FormState>();
//this will work fine when you move key outside the build();
#override
Widget build(BuildContext context){
}
You seem to know that the problem is in the key itself, as in #6783. The solution is to avoid constructing your validation key every time. So, you may do it like this (or even make it a widget's property):
class _TodoCreateDetailPageState extends State<TodoPage> {
final GlobalKey<FormState> _formKey = new GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
String _title = widget.todo == null ? "New TODO" : widget.todo.title;
String _message;
return new Scaffold(
appBar: new AppBar(
title: new Text(_title),
),
floatingActionButton: new FloatingActionButton(
child: new Icon(Icons.save), onPressed: null),
body: new Padding(
padding: new EdgeInsets.all(20.0),
child: new Form(
key: _formKey,
child: new Column(
children: <Widget>[
new TextField(
decoration: new InputDecoration(labelText: 'Title'),
onChanged: (String value) {
_title = value;
},
),
new TextField(
decoration: new InputDecoration(labelText: 'Message'),
onChanged: (String value) {
_message = value;
},
)
],
))),
);
}
I had the same problem, and found a solution for that, just define a controller variable outside the build method.
Use TextEditingController()
I think there's a much simpler solution that hasn't been mentioned yet and it has to do with the difference between GlobalKey and GlobalObjectKey.
A GlobalKey is only equal to itself and so each time your stateless widget is rebuilt, a new GlobalKey is created and the form is reset.
A GlobalObjectKey on the other hand is equal to any other GlobalObjectKey that has the same object:
GlobalObjectKey key1 = GlobalObjectKey('test');
GlobalObjectKey key2 = GlobalObjectKey('test');
key1 == key2; // True
So in this case, you should initialize your formKey as a GlobalObjectKey like this:
GlobalObjectKey<FormState> formKey = const GlobalObjectKey<FormState>('form');
I'm trying to create a SimpleDialog that allows the user to enter their name. But when it is displayed the dialog is half hidden by the on-screen keyboard:
How can I get the Dialog to be fully visible?
Edit: I find it strange that the homepage widget (FocusVisibilityDemo) recognises the reduced height and therefore adjusts the position of the 'Push Me' button to remain in the center. Unfortunately the dialog doesn't behave the same way.
Here is my code:
import 'package:flutter/material.dart';
class FocusVisibilityDemo extends StatefulWidget {
#override
_FocusVisibilityDemoState createState() => new _FocusVisibilityDemoState();
}
class _FocusVisibilityDemoState extends State<FocusVisibilityDemo> {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: new Text('Text Dialog Demo')),
body: new Center(
child: new RaisedButton(
onPressed: _showDialog,
child: new Text("Push Me"),
),
),
);
}
_showDialog() async {
await showDialog<String>(
context: context,
child: new AlertDialog(
contentPadding: const EdgeInsets.all(16.0),
content: new Row(
children: <Widget>[
new Expanded(
child: new TextField(
autofocus: true,
decoration: new InputDecoration(
labelText: 'Full Name', hintText: 'eg. John Smith'),
),
)
],
),
actions: <Widget>[
new FlatButton(
child: const Text('CANCEL'),
onPressed: () {
Navigator.pop(context);
}),
new FlatButton(
child: const Text('OPEN'),
onPressed: () {
Navigator.pop(context);
})
],
),
);
}
}
void main() {
runApp(new MaterialApp(home: new FocusVisibilityDemo()));
}
If your use case is to add multiple TextFields inside your Dialog so your main Form does not get crowded, I think it is better if you build something more customizable than AlertDialog and SimpleDialog as they are used for simple activities (confirmations, radios..etc).
Otherwise, why do you want to use a Dialog for a single TextField ?
When we add multiple TextFields we should be careful about our design choices since other people will interact with this view to fill in the data, in this case I prefer to use fullscreenDialog property of PageRoute class. I am not sure if SimpleDialog can be suitable for that in Flutter.
Here is a quick example on how to use a FullScreenDialog, I hope this help and you should be able to modify it the way you want:
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(home: new MyApp(),));
}
class MyApp extends StatefulWidget {
#override
MyAppState createState() => new MyAppState();
}
class MyAppState extends State<MyApp> {
FullScreenDialog _myDialog = new FullScreenDialog();
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Fill this form"),
),
body: new Column(
children: <Widget>[
new TextField(controller: new TextEditingController(
text: "Add a single text field"),),
new Card(child: new ListTile(
title: new Text("Click to add your top 3 amazing skills"),
subtitle: new Text(
"${_myDialog._skillOne} ${_myDialog._skillTwo} ${_myDialog
._skillThree}"),
onTap: () {
Navigator.push(context, new MaterialPageRoute(
builder: (BuildContext context) => _myDialog,
fullscreenDialog: true,
));
},
),
),
],
)
);
}
}
class FullScreenDialog extends StatefulWidget {
String _skillOne = "You have";
String _skillTwo = "not Added";
String _skillThree = "any skills yet";
#override
FullScreenDialogState createState() => new FullScreenDialogState();
}
class FullScreenDialogState extends State<FullScreenDialog> {
TextEditingController _skillOneController = new TextEditingController();
TextEditingController _skillTwoController = new TextEditingController();
TextEditingController _skillThreeController = new TextEditingController();
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Add your top 3 skills"),
),
body: new Padding(child: new ListView(
children: <Widget>[
new TextField(controller: _skillOneController,),
new TextField(controller: _skillTwoController,),
new TextField(controller: _skillThreeController,),
new Row(
children: <Widget>[
new Expanded(child: new RaisedButton(onPressed: () {
widget._skillThree = _skillThreeController.text;
widget._skillTwo = _skillTwoController.text;
widget._skillOne = _skillOneController.text;
Navigator.pop(context);
}, child: new Text("Save"),))
],
)
],
), padding: const EdgeInsets.symmetric(horizontal: 20.0),)
);
}
}
EDIT
After doing some research, it seems that this is a bug in the current Flutter version, the temporary fix is also documented in this issue.
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(home: new FocusVisibilityDemo()));
}
class FocusVisibilityDemo extends StatefulWidget {
#override
_FocusVisibilityDemoState createState() => new _FocusVisibilityDemoState();
}
class _FocusVisibilityDemoState extends State<FocusVisibilityDemo> {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: new Text('Text Dialog Demo')),
body: new Center(
child: new RaisedButton(
onPressed: _showDialog,
child: new Text("Push Me"),
),
),
);
}
_showDialog() async {
await showDialog<String>(
context: context,
child: new _SystemPadding(child: new AlertDialog(
contentPadding: const EdgeInsets.all(16.0),
content: new Row(
children: <Widget>[
new Expanded(
child: new TextField(
autofocus: true,
decoration: new InputDecoration(
labelText: 'Full Name', hintText: 'eg. John Smith'),
),
)
],
),
actions: <Widget>[
new FlatButton(
child: const Text('CANCEL'),
onPressed: () {
Navigator.pop(context);
}),
new FlatButton(
child: const Text('OPEN'),
onPressed: () {
Navigator.pop(context);
})
],
),),
);
}
}
class _SystemPadding extends StatelessWidget {
final Widget child;
_SystemPadding({Key key, this.child}) : super(key: key);
#override
Widget build(BuildContext context) {
var mediaQuery = MediaQuery.of(context);
return new AnimatedContainer(
padding: mediaQuery.viewInsets,
duration: const Duration(milliseconds: 300),
child: child);
}
}