How can I render only one Widget setState - dart

I have two easy basics example one is Works and second need some of explaining.
So, When I Clik Button in Example one it Works and setStaet rendering the page.
Second Example I using a body function that has setState of Button. When I click button nothing happen even with using setState notes if
the variable inside the parenthesis it does not render.
When I make Variable instance in class it works fine but I need to rendering Only One Button how?
Full code Example One
import 'package:flutter/material.dart';
main() => runApp(MaterialApp(
home: Home(),
));
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
bool istrue = false;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Works fine'),),
body: Center(child: body()),
);
}
Widget body() {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
onPressed: () {
setState(() {
istrue = !istrue;
});
},
child: Text('Click me'),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(istrue ? 'Boo!' : ''),
),
],
);
}
}
Full code Example two
import 'package:flutter/material.dart';
main() => runApp(MaterialApp(
home: Home(),
));
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
bool istrue = false;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Works fine'),),
body: Center(child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
body(),body(),
],
)),
);
}
Widget body() {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
onPressed: () {
setState(() {
istrue = !istrue;
});
},
child: Text('Click me'),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(istrue ? 'Boo!' : ''),
),
],
);
}
}
Thanks as sky.

I am having a bit of trouble understanding your question, but I also understand that English is not your first language. You seem to be asking, "How can I render only one button for example #2?". Please let me know if this is not your question so that I, and others, can help you.
This will only render one button,
import 'package:flutter/material.dart';
main() => runApp(MaterialApp(
home: Home(),
));
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
bool istrue = false;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Works fine'),),
body: Center(child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
onPressed: () {
setState(() {
istrue = !istrue;
});
},
child: Text('Click me'),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(istrue ? 'Boo!' : ''),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(istrue ? 'Boo!' : ''),
),
],
)),
);
}
}

You are calling a Column widget within another Column widget in the Scaffold widget in your second example. Why would you do that? There are many ways to structure that layout in the flutter API.
You can't have a new Column(new Column(...)); Its redundant.
Edit:
I pulled this from the flutter website at Column class:
The Column widget does not scroll (and in general it is considered an error to have more children in a Column than will fit in the available room). If you have a line of widgets and want them to be able to scroll if there is insufficient room, consider using a ListView.

Related

How to change background color of Scaffold widget programatically for whole application

I am new to the flutter application development and got stuck in a problem.My application contains near about 5-6 screens and all the screens contains the scaffold widget like this.
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFF332F43)
);
}
Now on all the screens i have the same concept and design like this and all the screens will share same backGround color.Now i have a button in all screens i.e. Change Theme button and on the button click of that Change Theme button i want to change all the screens Scaffold widget to be changed.Now how can i achieve this ? Please help me in my problem.
Flutter has predefined way to change background color of scaffold across app.
Just change it in MaterialApp Widget inside of your main.dart (main file).
MaterialApp(
title: 'Flutter',
theme: ThemeData(
scaffoldBackgroundColor: const Color(0xFF332F43),
),
);
Color color = Colors.blue; // make it at root level
void main() {
runApp(MaterialApp(home: Page1()));
}
In your page1 class, import above file.
class Page1 extends StatefulWidget {
#override
_Page1State createState() => _Page1State();
}
class _Page1State extends State<Page1> {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: color,
appBar: AppBar(title: Text("Page 1")),
body: Center(
child: Column(
children: <Widget>[
RaisedButton(
onPressed: () => Navigator.push(context, MaterialPageRoute(builder: (c) => Page2())),
child: Text("Go to Page 2"),
),
RaisedButton(
child: Text("Change color"),
onPressed: () => setState(() => color = Colors.red),
),
],
),
),
);
}
}
In your page2 class, import first file.
class Page2 extends StatefulWidget {
#override
_Page2State createState() => _Page2State();
}
class _Page2State extends State<Page2> {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: color,
appBar: AppBar(title: Text("Page 2")),
body: Center(
child: Column(
children: <Widget>[
RaisedButton(
onPressed: () => Navigator.pop(context),
child: Text("Back"),
),
RaisedButton(
child: Text("Change color"),
onPressed: () => setState(() => color = Colors.green),
),
],
),
),
);
}
}

Make cards with texts and buttons dynamically

I'm making Notes app. I made cards with text and buttons dynamically (Create by clicking the button). But I have problem with Changing Text on CURRENT card. For example, I have 3 cards with own texts and buttons and I want to change text on 2nd card but text is changing on the 3rd card. How can I solve this problem?
3 cards with texts and buttons
Change Text Page
In the past, I've tried making list to collect texts, but i dont know how to identify current card.
full main.dart
import 'package:flutter/material.dart';
import './changeTextPage.dart';
int count = 0;
String titlecard = '';
String textcard = '';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Notes',
theme: ThemeData(
primarySwatch: Colors.deepPurple
),
home: HomePage(title: 'Notes',),
);
}
}
class HomePage extends StatefulWidget {
HomePage({Key key, this.title}) : super(key: key);
final title;
#override
HomePageState createState() => HomePageState();
}
class HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
List<Widget> cards = new List.generate(count, (int i) => new MyCard());
return Scaffold(
appBar: AppBar(
title: Text('Notes'),
),
body: LayoutBuilder(
builder: (context, constraint) {
return Column(
children: <Widget>[
Container(
height: 650.0,
child: new ListView(
children: cards,
scrollDirection: Axis.vertical,
),
),
],
);
}
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
setState(() {
Navigator.push(context, MaterialPageRoute(
builder: (context) => changeText())
);
});
},
),
);
}
}
class MyCard extends StatefulWidget {
#override
myCard createState() => myCard();
}
class myCard extends State<MyCard> {
int myCount = count;
void click() {
setState(() {
Navigator.push(context, MaterialPageRoute(
builder: (context) => setNewText())
);
});
}
#override
Widget build(BuildContext context) {
return Center(
child: Card(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTile(
leading: Icon(Icons.album),
title: Text(titlecard),
subtitle: Text(textcard),
),
ButtonTheme.bar( // make buttons use the appropriate styles for cards
child: ButtonBar(
children: <Widget>[
FlatButton(
child: const Text('Change Text'),
onPressed: click,
),
FlatButton(
child: const Text('LISTEN'),
onPressed: () { /* ... */ },
),
],
),
),
],
),
),
);
}
}
class setNewText extends StatefulWidget {
#override
SetNewText createState() => SetNewText();
}
class SetNewText extends State<setNewText> {
final titleController = TextEditingController();
final textController = TextEditingController();
final formkey = GlobalKey<FormState>();
void _submit() {
setState(() {
if (formkey.currentState.validate()) {
formkey.currentState.save();
Navigator.pop(context);
titlecard = titleController.text;
textcard = textController.text;
}
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Change Title'),
),
body: Column(
children: <Widget>[
Card(
child: Padding(
padding: EdgeInsets.all(2.0),
child: Form(
key: formkey,
child: Column(
children: <Widget>[
TextFormField(
controller: titleController,
decoration: InputDecoration(
labelText: 'Title'
),
validator: (value) => value.length < 1 ? 'Invalid Title' : null,
onSaved: (value) => value = titleController.text,
),
TextFormField(
controller: textController,
decoration: InputDecoration(
labelText: 'Text'
),
validator: (text) => text.length < 1 ? 'Invalid Text' : null,
onSaved: (text) => text = textController.text,
)
],
),
),
),
),
FlatButton(
textColor: Colors.deepPurple,
child: Text('SUBMIT'),
onPressed: _submit,
),
],
)
);
}
}
changeTextPage.dart
import 'package:flutter/material.dart';
import './main.dart';
class changeText extends StatefulWidget {
#override
ChangeText createState() => ChangeText();
}
class ChangeText extends State<changeText> {
myCard s = myCard();
final titleController = TextEditingController();
final textController = TextEditingController();
final formkey = GlobalKey<FormState>();
void _submit() {
setState(() {
if (formkey.currentState.validate()) {
formkey.currentState.save();
Navigator.pop(context);
count++;
titlecard = titleController.text;
textcard = textController.text;
}
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Change Title'),
),
body: Column(
children: <Widget>[
Card(
child: Padding(
padding: EdgeInsets.all(2.0),
child: Form(
key: formkey,
child: Column(
children: <Widget>[
TextFormField(
controller: titleController,
decoration: InputDecoration(
labelText: 'Title'
),
validator: (value) => value.length < 1 ? 'Invalid Title' : null,
onSaved: (value) => value = titleController.text,
),
TextFormField(
controller: textController,
decoration: InputDecoration(
labelText: 'Text'
),
validator: (text) => text.length < 1 ? 'Invalid Text' : null,
onSaved: (text) => text = textController.text,
)
],
),
),
),
),
FlatButton(
textColor: Colors.deepPurple,
child: Text('SUBMIT'),
onPressed: _submit,
),
],
)
);
}
}
Okay, so you happen to make some common mistakes, one of which is critical.
most importantly don't use global variables! As you do with count, titlecard and textcard.
there is a practice to name stateful widgets with PascalCase and corresponding states just like the widget but prefixed with an underscore (_) to make it private and suffixed by the State word.
The correct approach for this (or one of them) would be to have a widget that would be your screen with a form to edit stuff and it would pop some struct with user values on submit:
class ChangeTextScreen extends StatefulWidget {
_ChangeTextScreenState createState() => _ChangeTextScreenState();
}
class _ChangeTextScreenState extends State<ChangeTextScreen> {
void _submit() {
setState(() {
formkey.currentState.save();
Navigator.pop(ChangeTextResult(title: titleController.text, text: textController.text));
});
}
// Rest of your code...
}
class ChangeTextResult {
final String title;
final String text;
ChangeTextResult({#required this.title, #required this.text});
}
You should also have a place where you store your notes in some kind of a list. Your main screen looks like a good place for it. Once your app will be bigger, think about using scoped_model or Redux or something.
So let's add a Note class and a list with your notes to your main screen:
class Note {
String title;
String text;
Note(this.title, this.text);
}
class HomePageState extends State<HomePage> {
List<Note> _notes = [Note('Test', 'Some test note')];
#override
Widget build(BuildContext context) {
ListView cards = ListView.builder(
itemCount: _notes.length,
itemBuilder: (context, index) => MyCard(
title: _notes[index].title,
text: _notes[index].text,
onEdit: (title, text) => setState(() { // We'll get back to that later
_notes[index].title = title;
_notes[index].text = text;
})
));
// (...)
Your MyCard widget (try to use better names next time) should contain some kind of information about its content, one of the best approaches would be to pass this info to its constructor, just like that:
class MyCard extends StatefulWidget {
final String title;
final String text;
final Function onEdit;
MyCard({Key key, #required this.title, #required this.text, #required this.onEdit}) : super(key: key);
#override
_MyCardState createState() => _MyCardState();
}
Having this Key parameter is a good practice.
And use those parameters in your _MyCardState class (I renamed it from _myCard):
// (...)
children: <Widget>[
ListTile(
leading: Icon(Icons.album),
title: Text(widget.title),
subtitle: Text(widget.text),
),
// (...)
Returning to the moment where you open your ChangeTextScreen, you should assign the result of Navigation.push() to a variable. This is your result, you can deal with it (once we check it for null, the user could have returned from this screen and then the result would be null).
void click() {
setState(() {
final ChangeTextResult result = Navigator.push(context, MaterialPageRoute(
builder: (context) => ChangeTextScreen())
);
if (result != null) {
widget.onEdit(result.title, result.text);
}
});
}
Do you remember that onEdit parameter (I mentioned it in a comment in the code above)? We call that parameter here.
That's it I think. I could have mixed some concepts of your app, but I think you'll manage to get my point anyways.
I quite rewrote all of your code. I think it will be easier for you to start again from scratch and have those tips in mind. Also, try to Google some similar things (like a simple Todo application) or do Getting started from flutter.io with part two! That should give you a nice idea on how to resolve that common problem in Flutter.
And also, read about good practises in Flutter and Dart. Things like correctly formatting your code are really important.
BTW that's my longest answer on Stack Overflow so far. I hope you'll appreciate that.

Flutter dart add list to children

I am new on dart, I just want to add a list of my data using map (store.state.availablePage.map) to the children of ListView, but I already have some item on the ListView.
Here the sample code I want :
class MgDrawer extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StoreBuilder<AppState>(
builder: (context, store) {
return Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
Text("Title"),
store.state.availablePage.map((value) {
return ListTile(
title: Text("Title"),
onTap: () {},
);
}).toList(),
],
),
);
},
);
}
}
Please help me how I can achieve that?
Update: the code above is not compiled.
Updates Dart Lang version > 2.2.2, can be achieve using below code :
class MgDrawer extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StoreBuilder<AppState>(
builder: (context, store) {
return Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
Text("Title"),
...store.state.availablePage.map((value) {
return ListTile(
title: Text("Title"),
onTap: () {},
);
}).toList(),
],
),
);
},
);
}
}
You ListView is having Text(Widget) and a Array of ListTile(Array of Widgets) which means ListView(children: [Widget, [Widget]]).
But it should be ListView(children: [Widget1, Widget2, Widget3,...]). Below code might help
class MgDrawer extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StoreBuilder<AppState>(
builder: (context, store) {
List<Widget> list = store.state.availablePage.map((value) {
return ListTile(
title: Text("Title"),
onTap: () {},
);
}).toList();
list.insert(0, Text("Title"));
return Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: list,
),
);
},
);
}
}
If for some reason someone is unable to use "..." operator, there is also another solution. It is not as elegant as "..." operator, but it also works.
You can just use ..addAll(list) at the end of the list.
Here is how it would look like in given example:
class MgDrawer extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StoreBuilder<AppState>(
builder: (context, store) {
return Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
Text("Title"),
]..addAll(store.state.availablePage.map((value) {
return ListTile(
title: Text("Title"),
onTap: () {},
);
}).toList(),),
),
);
},
);
}
}

Flutter Access parent Scaffold from different dart file

I have this:
final GlobalKey<ScaffoldState> _scaffoldkey = new GlobalKey<ScaffoldState>();
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
key: _scaffoldkey,
drawer: Menu(),
appBar: AppBar(
title: Container(
child: Text('Dashboard'),
),
bottom: TabBar(
tabs: <Widget>[
...
],
),
),
body: TabBarView(
children: <Widget>[
...
],
),
),
);
}
}
Now, the drawer: Menu() is imported from another menu.dart file, which looks like this:
class Menu extends StatelessWidget {
final GlobalKey<ScaffoldState> drawerKey = new GlobalKey<ScaffoldState>();
#override
Widget build(BuildContext context) {
return new Drawer(
key: drawerKey,
child: new ListView(
children: <Widget>[
new ListTile(
dense: true,
title: new Text('My Text'),
onTap: () {
// On tap this, I want to show a snackbar.
scaffoldKey.currentState.showSnackBar(showSnack('Error. Could not log out'));
},
),
],
),
);
}
}
With the above approach, I get
NoSuchMethodError: The method 'showSnackBar' was called on null.
An easy solution is to tuck the entire menu.dart contents in the drawer: ... directly.
Another way I'm looking at is being able to reference the parent scaffold in order to display the snackbar.
How can one achieve that?
Why can't one even just call the snackbar from anywhere in Flutter and compulsorily it has to be done via the Scaffold? Just why?
You should try to avoid using GlobalKey as much as possible; you're almost always better off using Scaffold.of to get the ScaffoldState. Since your menu is below the scaffold in the widget tree, Scaffold.of(context) will do what you want.
The reason what you're attempting to do doesn't work is that you are creating two seperate GlobalKeys - each of which is its own object. Think of them as global pointers - since you're creating two different ones, they point to different things. And the state should really be failing analysis since you're passing the wrong type into your Drawer's key field...
If you absolutely have to use GlobalKeys for some reason, you would be better off passing the instance created in your outer widget into your Menu class as a member i.e. this.scaffoldKey, but this isn't recommended.
Using Scaffold.of, this is what your code would look like in the onTap function:
onTap: () {
// On tap this, I want to show a snackbar.
Scaffold.of(context).showSnackBar(showSnack('Error. Could not log out'));
},
You can achieve this functionality by using builder widget you don't need to make separate GlobalKey or pass key as a parameter. Just wrap a widget to Builder widget
class CustomDrawer extends StatelessWidget {#override Widget build(BuildContext context) {
return new Drawer(
child: new ListView(
children: <Widget>[
new Builder(builder: (BuildContext innerContext) {
return ListTile(
dense: true,
title: new Text('My Text'),
onTap: () {
Navigator.of(context).pop();
Scaffold.of(innerContext).showSnackBar(SnackBar(
content: Text('Added added into cart'),
duration: Duration(seconds: 2),
action: SnackBarAction(label: 'UNDO', onPressed: () {}),
));
}
);
})
],
),
);}}
From your first question
In other to reference the parent scaffold in the menu widget you can pass the _scaffoldkey to the menu widget as parameter and use ScaffoldMessenger.of() to show snackbar as shown below
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// Root Widget
#override
Widget build(BuildContext context) {
return MaterialApp(
// App name
title: 'Flutter SnackBar',
// Theme
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Test(title: 'SnackBar'),
);
}
}
class Test extends StatefulWidget {
final String? title;
final GlobalKey<ScaffoldState> _scaffoldkey = new GlobalKey<ScaffoldState>();
Test({#required this.title});
#override
_TestState createState() => _TestState();
}
class _TestState extends State<Test> {
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
key: widget._scaffoldkey,
drawer: Menu(parentScaffoldkey:widget._scaffoldkey),
appBar: AppBar(
title: Container(
child: Text('Dashboard'),
),
bottom: TabBar(
tabs: <Widget>[
Tab(text:"Home"),
Tab(text:"About")
],
),
),
body: TabBarView(
children: <Widget>[
Text("Home"),
Text("About")
],
),
),
);
}
}
Menu part as shown
class Menu extends StatelessWidget {
final parentScaffoldkey;
Menu({this.parentScaffoldkey});
#override
Widget build(BuildContext context) {
return new Drawer(
child: new ListView(
children: <Widget>[
new ListTile(
dense: true,
title: new Text('My Text'),
onTap: () {
// On tap show a snackbar.
// ScaffoldMessenger will call the nearest Scaffold to show snackbar
ScaffoldMessenger.of(this.parentScaffoldkey.currentContext).showSnackBar(SnackBar(content:Text('Error. Could not log out')));
},
),
],
),
);
}
}
Also,you have to call snackbar via Scaffold because it provides the SnackBar API and manages it

Show a text field dialog without being covered by keyboard?

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

Resources