Handling the app bar separately - dart

I'm new to flutter and dart. I am trying to learn both by developing an app. I have taken the udacity course but it only gave me the basics. What I want to know is if it is possible to handle the appBar code separately.
Currently, this is what I have:
class HomePage extends StatelessWidget {
HomePage({Key key, this.title}) : super(key: key);
final String title;
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
leading: new IconButton(
icon: new Icon(Icons.menu),
tooltip: 'Menu',
onPressed: () {
print('Pressed Menu');
},
),
title: new Text(title),
titleSpacing: 0.0,
actions: <Widget>[
new Row(
children: <Widget>[
new Column(
children: <Widget>[
new Text(
'Firstname Lastname',
textAlign: TextAlign.right,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 12.0,
),
),
new Text("username#email.com",
textAlign: TextAlign.right,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 12.0,
)),
],
mainAxisAlignment: MainAxisAlignment.center,
),
new Padding(
padding: new EdgeInsets.all(8.0),
child: new Image.network(
'https://s5.postimg.cc/bycm2rrpz/71f3519243d136361d81df71724c60a0.png',
width: 42.0,
height: 42.0,
),
),
],
),
],
),
body: new Center(
child: Text('Hello World!'),
),
);
}
}
However, I would like to handle the appbar code separately as I believe it can swell a bit more. I have tried something like this:
class HomePage extends StatelessWidget {
HomePage({Key key, this.title}) : super(key: key);
final String title;
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: MyAppBar(),
body: new Center(
child: Text('Hello World!'),
),
);
}
}
class MyAppBar extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new AppBar(
leading: new IconButton(
icon: new Icon(Icons.menu),
tooltip: 'Menu',
onPressed: () {
print('Pressed Menu');
},
),
title: new Text(title),
titleSpacing: 0.0,
actions: <Widget>[
new Row(
children: <Widget>[
new Column(
children: <Widget>[
new Text(
'Firstname Lastname',
textAlign: TextAlign.right,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 12.0,
),
),
new Text("username#email.com",
textAlign: TextAlign.right,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 12.0,
)),
],
mainAxisAlignment: MainAxisAlignment.center,
),
new Padding(
padding: new EdgeInsets.all(8.0),
child: new Image.network(
'https://s5.postimg.cc/bycm2rrpz/71f3519243d136361d81df71724c60a0.png',
width: 42.0,
height: 42.0,
),
),
],
),
],
);
}
}
But then I'm getting this message:
The argument type 'MyAppBar' can't be assigned to the parameter type 'PreferredSizeWidget'
I have an intuition that this might not be possible. As I said, I'm new to flutter and dart and I have tried looking in the documentation and in other posts to no avail. Sorry if this seems stupid. I would just really like for someone to point me to the documentation, if there is any, on how to achieve this kind of things or any resource that can help me better understand how this works.
For your kind and valuable help, many thanks in advance!

the appBar widget must implement the PreferredSizeWidget class so you have to :
class MyAppBar extends StatelessWidget implements PreferredSizeWidget
and then you have to implemt this method also
Size get preferredSize => new Size.fromHeight(kToolbarHeight);
Full Example :
class MyAppBar extends StatelessWidget implements PreferredSizeWidget {
#override
Widget build(BuildContext context) {
return new AppBar(
leading: new IconButton(
icon: new Icon(Icons.menu),
tooltip: 'Menu',
onPressed: () {
print('Pressed Menu');
},
),
title: new Text(title),
titleSpacing: 0.0,
actions: <Widget>[
new Row(
children: <Widget>[
new Column(
children: <Widget>[
new Text(
'Firstname Lastname',
textAlign: TextAlign.right,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 12.0,
),
),
new Text("username#email.com",
textAlign: TextAlign.right,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 12.0,
)),
],
mainAxisAlignment: MainAxisAlignment.center,
),
new Padding(
padding: new EdgeInsets.all(8.0),
child: new Image.network(
'https://s5.postimg.cc/bycm2rrpz/71f3519243d136361d81df71724c60a0.png',
width: 42.0,
height: 42.0,
),
),
],
),
],
);
}
#override
Size get preferredSize => new Size.fromHeight(kToolbarHeight);
}

class MyAppBar extends StatelessWidget implements PreferredSizeWidget {
#override
Widget build(BuildContext context) {
return AppBar(
backgroundColor: Colors.blueGrey,
title: Text('News App'),
centerTitle: true,
leading: Icon(Icons.menu ),
);
}
#override
// TODO: implement preferredSize
Size get preferredSize => new Size.fromHeight(48);
}

Related

Flutter - Not loading full design in ios device

I am developing new application in flutter. This application works well in android simulator, android real device and in iOS simulator. In iOS real device application works well in first launch but when i restart the app it shows only the textfield. Please help me to solve this issue.
main.dart:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:moonlight/screens/sign_in.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Moonlight',
theme: ThemeData(fontFamily: 'Prata'),
home: SignInScreen(),
);
}
}
sign_in.dart:
import 'package:flutter/material.dart';
import 'package:moonlight/screens/sign_up.dart';
import 'package:moonlight/utils/constants.dart';
import 'package:moonlight/widget/textButton.dart';
import 'package:moonlight/widget/textFiled.dart';
import '../services/dimensions.dart';
class SignInScreen extends StatefulWidget {
const SignInScreen({Key? key}) : super(key: key);
#override
State<SignInScreen> createState() => _SignInScreenState();
}
class _SignInScreenState extends State<SignInScreen> {
final TextEditingController emailController = new
TextEditingController();
final TextEditingController passwordController = new
TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
preferredSize:
Size.fromHeight(Dimensions().getResponsiveSize(170)),
child: Container(
color: appBarColor,
child: AppBar(
backgroundColor: appBarColor,
toolbarHeight: Dimensions().getResponsiveSize(170),
centerTitle: true,
title: Column(
children: [
Container(
//color: Colors.red,
width: Dimensions().getResponsiveSize(200),
height: Dimensions().getResponsiveSize(40),
//width: 200,
//color: Colors.red,
child: Image.asset(
logoUrl,
fit: BoxFit.fitHeight,
//height: Dimensions().getResponsiveSize(50),
//width: Dimensions().getResponsiveSize(200),
//width: 50,
),
),
SizedBox(height:
Dimensions().getResponsiveSize(20),),
Text('Sign In',
style: TextStyle(
fontSize: Dimensions().getResponsiveSize(25),
fontWeight: FontWeight.bold
),
),
SizedBox(height: Dimensions().getResponsiveSize(5),),
Text('Welcome',
style: TextStyle(
fontSize: Dimensions().getResponsiveSize(15),
),
),
],
),
),
)),
bottomNavigationBar: GestureDetector(
onTap: () {
},
child: Container(
color: appBarColor,
height: Dimensions().getResponsiveSize(50),
child: Center(
child: Text(
'Go',
style: TextStyle(color: Colors.white, fontSize:
Dimensions().getResponsiveSize(15),
fontWeight: FontWeight.bold
),
)),
),
),
body: Padding(
padding: EdgeInsets.symmetric(horizontal:
Dimensions().getResponsiveSize(20)),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
TextFieldInput(
controller: emailController,
icon: Icons.email,
text: 'Email',
),
SizedBox(
height: Dimensions().getResponsiveSize(10),
),
TextFieldInput(
controller: passwordController,
icon: Icons.lock_rounded,
text: 'Password',
isObscure: true,
),
Row(
children: [
Spacer(),
TextButtonWidget(
onPressed:forgotPassword,
text: 'Forgot Password?',
size: Dimensions().getResponsiveSize(15),
color: appBarColor,
),
],
),
SizedBox(
height: Dimensions().getResponsiveSize(20),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
color: Colors.grey,
width: Dimensions().getResponsiveSize(70),
height: 1.2,
),
SizedBox(
width: Dimensions().getResponsiveSize(10),
),
Text(
'OR',
style: TextStyle(color: Colors.grey,
fontSize: Dimensions().getResponsiveSize(15)
),
),
SizedBox(
width: Dimensions().getResponsiveSize(10),
),
Container(
color: Colors.grey,
width: Dimensions().getResponsiveSize(70),
height: 1.2,
),
],
),
SizedBox(
height: Dimensions().getResponsiveSize(20),
),
TextButtonWidget(
onPressed: signUpScreen,
text: 'Sign Up',
size: Dimensions().getResponsiveSize(15),
color: appBarColor,
),
],
),
),
);
}
forgotPassword(){
}
signUpScreen(){
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const SignUpScreen()),
);
}
}
dimensions.dart
import 'package:get/get.dart';
class Dimensions{
static double shortestSide = Get.size.shortestSide;
getResponsiveSize(dynamic size) {
dynamic x = (size/392.72727272727275) * 100;
return (shortestSide*x)/100;
}
}

How do I remove a child that's been pressed from ListView

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

TextFormField is not working properly, its blinking continuously

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

bottomNavigationBar using iPhone X

I have an issue with a bottomNavigationBar, the issue happens only on iPhone X, as there appears some padding below the BNB as if it were inside a SafeArea widget (and its not)
Well, how can I remove that padding? or maybe color it somehow?
This is my code for the build function
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: _buildAppBar(),
drawer: _buildDrawer(),
body: _isLoading
? Center(
child: CircularProgressIndicator(),
)
: new Container(
color: Colors.white,
child: _unauthorizedOrders()),
// floatingActionButton: FloatingActionButton(
// onPressed: () {},
// backgroundColor: primaryColor,
// child: Icon(Icons.flash_on, size: 30.0,),
// tooltip: 'Authorize Orders',
// ),
// floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
backgroundColor: Colors.red,
bottomNavigationBar: BottomAppBar(
child: Container(
height: 40.0,
color: primaryColor,
child: Row(
children: <Widget>[
// Padding(
// padding: const EdgeInsets.only(left: 10.0),
// child: Text(
// 'Orders: ${orders.length}',
// style: TextStyle(
// color: Colors.white,
// fontSize: 18.0,
// fontWeight: FontWeight.bold),
// ),
// ),
],
),
)),
);
}
EDIT: I have added the backgroundColor to the scaffold, removed the docked FAB and wrapped the body inside a container to paint it white, still doesn't work, I have updated the code above to show it
Use
SafeArea(
child: BottomAppBar(...)
);
A work-around will be to set the backgroundColor of your Scaffold to the same color as your BottomNavigationBar and have your content in a container with the color that you want.
Edit:
Here is a Sample code:
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'BNB Demo on iPhone X',
theme: new ThemeData(
brightness: Brightness.dark,
primaryColor: Colors.black,
),
home: new MyHomePage(title: 'BNB Demo on iPhone X'),
);
}
}
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> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return new SafeArea(
child: new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(
'You have pushed the button this many times:',
),
new Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add, color: Colors.white,),
backgroundColor: Colors.black,
onPressed: _incrementCounter,
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
bottomNavigationBar: new BottomAppBar(
child: Container(
height: 40.0,
color: Colors.black,
),
),
),
);
}
}
I had the same problem with this bottomAppBar.
I only erased the color attibute.
Hope it helps to someone.
BottomAppBar(
elevation: 0.0,
shape: widget.notchedShape,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.0), topRight: Radius.circular(20.0)),
color: Colors.white),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: items)
),
color: Colors.teal[50]);

Flutter - Generate in app interactivity

I'm kind of lost in generating interactivity on Flutter.
I'm trying to make tapping the FlatButtons the value shown above, and in the order it was tapped.
For example, tap number 1, then 2, 1, 1, 1 and last 2 should appear $ 12111, remembering quite a list.
Taping on the backspace icon removes the last number that has entered the list.
I am not aware of generating this communication between classes.
Can you help me? I'm trying to use the StatefulWidget but I'm not succeeding.
Below I left the code that generates the screen described above.
main.dart
import "package:flutter/material.dart";
void main() {
runApp(new KeyboardApp());
}
class KeyboardApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new HomePage(),
);
}
}
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new ListView (
children: <Widget>[
new Number(),
new Keyboard(),
],
),
);
}
}
class NumberState extends StatefulWidget {
NumberList createState() => new NumberList();
}
class NumberList extends State<NumberState> {
List<String> numbers = <String>[];
String number;
#override
Widget build(BuildContext context) {
number = this.numbers.join('');
return new Text(
this.number,
style: new TextStyle(
fontFamily: 'Roboto',
color: new Color(0xFFFFFFFF),
fontSize: 45.0
)
);
}
}
class Number extends StatelessWidget {
final Color color = new Color(0xFFE57373);
#override
Widget build(BuildContext context) {
return new Container(
height: 145.0,
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Container(
padding: new EdgeInsets.only(right: 16.0, top: 35.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
new Text(
'\$ ',
style: new TextStyle(
fontFamily: 'Roboto',
color: new Color(0xFFFFFFFF),
fontSize: 20.0
)
),
new NumberState(),
],
)
)
],
),
color: color,
);
}
}
class Keyboard extends StatelessWidget {
final Color color = new Color(0xFFE57373);
var list = new NumberList().numbers;
#override
Widget build(BuildContext context) {
return new Container(
padding: new EdgeInsets.only(right: 15.0, left: 15.0, top: 47.0, bottom: 20.0),
child: new Column(
children: <Widget>[
new Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
new FlatButton(
textColor: color,
child: new Text(
'1',
style: new TextStyle(
fontSize: 35.0
),
),
onPressed: () {
this.list.add('1');
},
),
new FlatButton(
textColor: color,
child: new Text(
'2',
style: new TextStyle(
fontSize: 35.0
),
),
onPressed: () {
this.list.add('2');
},
),
new FlatButton(
textColor: color,
child: new Icon(
Icons.backspace,
size: 35.0
),
onPressed: () {
this.list.removeLast();
},
),
],
),
],
),
);
}
}
Check out the Flutter interactivity tutorial. At a high level (heh), your problem is that you are trying to store state in the leaves of your widget tree. You should store your state higher up in your tree and then pass it down to the children.
The example below uses ValueNotifier but you can also pass state around using streams, callbacks, or even Firebase Database.
import "package:flutter/material.dart";
void main() {
runApp(new KeyboardApp());
}
class KeyboardApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new HomePage(),
);
}
}
class HomePage extends StatefulWidget {
HomePageState createState() => new HomePageState();
}
class HomePageState extends State<HomePage> {
ValueNotifier<List<int>> numbers = new ValueNotifier<List<int>>(<int>[]);
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new ListView (
children: <Widget>[
new NumberDisplay(numbers: numbers),
new Keyboard(numbers: numbers),
],
),
);
}
}
class NumberDisplay extends AnimatedWidget {
NumberDisplay({ this.numbers }) : super(listenable: numbers);
final ValueNotifier<List<int>> numbers;
final Color _color = new Color(0xFFE57373);
#override
Widget build(BuildContext context) {
return new Container(
height: 145.0,
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Container(
padding: new EdgeInsets.only(right: 16.0, top: 35.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
new Text(
'\$ ',
style: new TextStyle(
fontFamily: 'Roboto',
color: new Color(0xFFFFFFFF),
fontSize: 20.0
)
),
new Text(
this.numbers.value.join(''),
style: new TextStyle(
fontFamily: 'Roboto',
color: new Color(0xFFFFFFFF),
fontSize: 45.0
),
),
],
),
),
],
),
color: _color,
);
}
}
class Keyboard extends StatelessWidget {
Keyboard({ this.numbers });
final ValueNotifier<List<int>> numbers;
final Color _color = new Color(0xFFE57373);
#override
Widget build(BuildContext context) {
return new Container(
padding: new EdgeInsets.only(right: 15.0, left: 15.0, top: 47.0, bottom: 20.0),
child: new Column(
children: <Widget>[
new Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
new FlatButton(
textColor: _color,
child: new Text(
'1',
style: new TextStyle(
fontSize: 35.0
),
),
onPressed: () {
numbers.value = new List.from(numbers.value)..add(1);
},
),
new FlatButton(
textColor: _color,
child: new Text(
'2',
style: new TextStyle(
fontSize: 35.0
),
),
onPressed: () {
numbers.value = new List.from(numbers.value)..add(2);
},
),
new FlatButton(
textColor: _color,
child: new Icon(
Icons.backspace,
size: 35.0
),
onPressed: () {
numbers.value = new List.from(numbers.value)..removeLast();
},
),
],
),
],
),
);
}
}

Resources