Flutter Checkbox not working in AlertDialog [duplicate] - checkbox

I'm trying to create a Radio in a showDialog, however the animation that occurs on Radio does not appear in showDialog.
For example: when tapped in foo2 nothing happens, and when you exit in showDialog and go back to it, foo2 is selected.
Below is the code and a gif showing what is happening:
import "package:flutter/material.dart";
void main() {
runApp(new ControlleApp());
}
class ControlleApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: "My App",
home: new HomePage(),
);
}
}
class HomePage extends StatefulWidget {
#override
HomePageState createState() => new HomePageState();
}
enum _RadioGroup {
foo1,
foo2
}
class HomePageState extends State<HomePage> {
_RadioGroup _itemType = _RadioGroup.foo1;
void changeItemType(_RadioGroup type) {
setState(() {
_itemType = type;
});
}
void showDemoDialog<T>({ BuildContext context, Widget child }) {
showDialog<T>(
context: context,
child: child,
);
}
#override
Widget build(BuildContext context){
return new Scaffold(
appBar: new AppBar(backgroundColor: new Color(0xFF26C6DA)),
body: new Container(
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new InkWell(
onTap: (){
showDemoDialog<String>(
context: context,
child: new SimpleDialog(
title: const Text("show"),
children: <Widget>[
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Radio<_RadioGroup>(
groupValue: _itemType,
value: _RadioGroup.foo1,
onChanged: changeItemType
),
const Text("foo1"),
new Radio<_RadioGroup>(
groupValue: _itemType,
value: _RadioGroup.foo2,
onChanged: changeItemType
),
const Text("foo2"),
],
)
],
)
);
},
child: new Container(
margin: new EdgeInsets.only(top: 16.0, bottom: 8.0),
child: new Text("Show"),
),
)
],
),
)
);
}
}

Remember that components are immutable.
When you call showDialog, the content of that dialog won't change even if HomePage does.
The solution is easy. You need to refactor a bit your code to something like :
showDialog(
context: context,
builder: (context) => MyForm()
)
and instead of changing the state of HomePage, you instead change the state of MyForm.
example :
class Test extends StatelessWidget {
void onSubmit(String result) {
print(result);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: RaisedButton(
onPressed: () => showDialog(context: context, builder: (context) => MyForm(onSubmit: onSubmit)),
child: Text("dialog"),
),
),
);
}
}
typedef void MyFormCallback(String result);
class MyForm extends StatefulWidget {
final MyFormCallback onSubmit;
MyForm({this.onSubmit});
#override
_MyFormState createState() => _MyFormState();
}
class _MyFormState extends State<MyForm> {
String value = "foo";
#override
Widget build(BuildContext context) {
return SimpleDialog(
title: Text("My form"),
children: <Widget>[
Radio(
groupValue: value,
onChanged: (value) => setState(() => this.value = value),
value: "foo",
),
Radio(
groupValue: value,
onChanged: (value) => setState(() => this.value = value),
value: "bar",
),
FlatButton(
onPressed: () {
Navigator.pop(context);
widget.onSubmit(value);
},
child: new Text("submit"),
)
],
);
}
}

Related

No MediaQuery ancestor could be found starting from the context that was passed to MediaQuery.of()

Okay so my code work (I have some things to fix but I can run It )but I have this error, I think the problem is on the main because that's why the terminal say but I don't know how I can solve it. If somoene can help me with that I will be very greateful as always ty
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: Firebase.initializeApp(),
builder: (context, snapshot) {
if(snapshot.hasError){
return Scaffold(
body: Center(
child: Text(snapshot.error.toString(
),),
),
);
}
if(snapshot.connectionState == ConnectionState.waiting){
return loading();
}
return MaterialApp(
themeMode: ThemeMode.system,
theme: myTheme.lightTheme,
darkTheme: myTheme.darkTheme,
home: SplashScreen(
),
}
class SplashScreen extends StatefulWidget {
#override
_SplashScreenState createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
#override
void initState() {
// TODO: implement initState
super.initState();
Timer(Duration(seconds: 4), () {
Navigator.of(context)
.pushReplacement(MaterialPageRoute(builder: (_) => Todolist(
)));
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
'stuffandmore/panda.png',
height: 230,

Flutter the values in the array all become the same

Please understand that I am not good at English because I am a foreigner.
There was a problem while I was programming.
I was going to put each object in the array. We succeeded in putting the object in. But there was a problem with all the objects in the array being the same.
I want to solve this problem.
I'd appreciate it if you could help me.
Main.dart :
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'Page/FirstPage.dart';
import 'Page/FourPage.dart';
import 'Page/SecondPage.dart';
import 'Page/ThirdPage.dart';
import 'module/goal.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => Index()),
ChangeNotifierProvider(create: (_) => Goal('None')),
ChangeNotifierProvider(create: (_) => GoalList())
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Todo App',
home: MainPage(),
),
);
}
}
class MainPage extends StatefulWidget {
#override
_MainPageState createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
var currentTab = [FirstPage(), SecondPage(), ThirdPage(), FourPage()];
#override
Widget build(BuildContext context) {
Index currentIndex = Provider.of<Index>(context);
Goal goal = Provider.of<Goal>(context);
return Scaffold(
body: IndexedStack(
index: currentIndex.currentIndex,
children: currentTab,
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: currentIndex.currentIndex,
onTap: (index) {
currentIndex.currentIndex = index;
},
type: BottomNavigationBarType.fixed,
// 하단바 아이콘 고정
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.add_circle), title: Text('Todo Create')),
BottomNavigationBarItem(
icon: Icon(Icons.format_list_bulleted),
title: Text('Todo List')),
BottomNavigationBarItem(
icon: Icon(Icons.calendar_today), title: Text('none')),
BottomNavigationBarItem(
icon: Icon(Icons.settings), title: Text('none')),
],
selectedItemColor: Colors.black87,
// 선택된 index 색깔
unselectedItemColor: Colors.black54,
// 선택안된 index 색깔
),
);
}
}
Goal.dart
import 'package:flutter/cupertino.dart';
// 아이콘 설정 , 제목 , 기간 ,
class Goal with ChangeNotifier {
String _name;
String get getName => _name;
set setName(String name)=> _name = name;
Goal(this._name);
#override String toString() => _name;
}
class Index with ChangeNotifier {
int _currentIndex = 0;
get currentIndex => _currentIndex;
set currentIndex(int index) {
_currentIndex = index;
notifyListeners();
}
}
class GoalList with ChangeNotifier {
List<Goal> goalList = [];
Goal getGoal;
addGoalInList() {
goalList.add(getGoal);
notifyListeners();
}
}
FirstPage.dart
import 'package:flutter/material.dart';
import 'package:goalapp/module/goal.dart';
import 'package:provider/provider.dart';
class FirstPage extends StatefulWidget {
#override
_FirstPageState createState() => _FirstPageState();
}
// 객체를 만들 클래스를 생성
// 생성된 객체를 내부저장소에 저장
class _FirstPageState extends State<FirstPage> {
final _formKey = GlobalKey<FormState>();
TextEditingController _names = TextEditingController();
#override
void dispose() {
_names.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
Index currentIndex = Provider.of<Index>(context);
Goal goal = Provider.of<Goal>(context);
GoalList goalList = Provider.of<GoalList>(context);
return Scaffold(
appBar: AppBar(
title: Text('Todo add'),
),
body: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Column(
children: <Widget>[
Container(
width: 200,
height: 200,
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
TextFormField(
controller: _names,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(10))),
filled: true,
hintText: 'Todo Name'),
),
],
),
),
),
RaisedButton(
onPressed: () {
goal.setName = _names.text;
goalList.getGoal = goal;
goalList.addGoalInList();
currentIndex.currentIndex = 1;
},
child: Text('Create'),
)
],
)
],
),
);
}
}
SecondPage.dart
import 'package:flutter/material.dart';
import 'package:goalapp/module/goal.dart';
import 'package:provider/provider.dart';
class SecondPage extends StatefulWidget {
#override
_SecondPageState createState() => _SecondPageState();
}
class _SecondPageState extends State<SecondPage> {
#override
Widget build(BuildContext context) {
Goal goal = Provider.of<Goal>(context);
GoalList goalList = Provider.of<GoalList>(context);
return Scaffold(
appBar: AppBar(
title: Text('Todo ListView'),
),
body: Column(
children: <Widget>[
Expanded(
child: Consumer<GoalList>(builder: (context, goal, child) {
return ListView.separated(
itemCount: goal.goalList.length,
itemBuilder: (context, index) {
return Container(
child: ListTile(
title: Text(goalList.goalList[index].getName),
subtitle: Text('2020.07.16 ~ 2020.08.16'),
),
);
},
separatorBuilder: (context, index) {
return Divider();
},
);
}),
),
RaisedButton(
onPressed: () {
print(goalList.goalList[0]);
},
child: Text('List[0]'),
),
RaisedButton(
onPressed: () {
print(goalList.goalList[1]);
},
child: Text('List[1]'),
),
],
));
}
}
You can copy paste run full code below
Step 1: Change GoalList's addGoalInList(Goal goal)
class GoalList with ChangeNotifier {
List<Goal> goalList = [];
Goal getGoal;
addGoalInList(Goal goal) {
goalList.add(goal);
notifyListeners();
}
}
Step 2: You do not need Goal goal = Provider.of<Goal>(context);
#override
Widget build(BuildContext context) {
Index currentIndex = Provider.of<Index>(context);
// Goal goal = Provider.of<Goal>(context);
Step 3: Add goal with Goal goal = Goal(_names.text); then goalList.addGoalInList(goal);
RaisedButton(
onPressed: () {
Goal goal = Goal(_names.text);
//goal.setName = _names.text;
//goalList.getGoal = goal;
goalList.addGoalInList(goal);
currentIndex.currentIndex = 1;
},
child: Text('Create'),
)
working demo
full code
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:flutter/cupertino.dart';
// 아이콘 설정 , 제목 , 기간 ,
class Goal with ChangeNotifier {
String _name;
String get getName => _name;
set setName(String name)=> _name = name;
Goal(this._name);
#override String toString() => _name;
}
class Index with ChangeNotifier {
int _currentIndex = 0;
get currentIndex => _currentIndex;
set currentIndex(int index) {
_currentIndex = index;
notifyListeners();
}
}
class GoalList with ChangeNotifier {
List<Goal> goalList = [];
Goal getGoal;
addGoalInList(Goal goal) {
goalList.add(goal);
notifyListeners();
}
}
class FirstPage extends StatefulWidget {
#override
_FirstPageState createState() => _FirstPageState();
}
// 객체를 만들 클래스를 생성
// 생성된 객체를 내부저장소에 저장
class _FirstPageState extends State<FirstPage> {
final _formKey = GlobalKey<FormState>();
TextEditingController _names = TextEditingController();
#override
void dispose() {
_names.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
Index currentIndex = Provider.of<Index>(context);
// Goal goal = Provider.of<Goal>(context);
GoalList goalList = Provider.of<GoalList>(context);
return Scaffold(
appBar: AppBar(
title: Text('Todo add'),
),
body: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Column(
children: <Widget>[
Container(
width: 200,
height: 200,
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
TextFormField(
controller: _names,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(10))),
filled: true,
hintText: 'Todo Name'),
),
],
),
),
),
RaisedButton(
onPressed: () {
Goal goal = Goal(_names.text);
//goal.setName = _names.text;
//goalList.getGoal = goal;
goalList.addGoalInList(goal);
currentIndex.currentIndex = 1;
},
child: Text('Create'),
)
],
)
],
),
);
}
}
class SecondPage extends StatefulWidget {
#override
_SecondPageState createState() => _SecondPageState();
}
class _SecondPageState extends State<SecondPage> {
#override
Widget build(BuildContext context) {
Goal goal = Provider.of<Goal>(context);
GoalList goalList = Provider.of<GoalList>(context);
return Scaffold(
appBar: AppBar(
title: Text('Todo ListView'),
),
body: Column(
children: <Widget>[
Expanded(
child: Consumer<GoalList>(builder: (context, goal, child) {
return ListView.separated(
itemCount: goal.goalList.length,
itemBuilder: (context, index) {
return Container(
child: ListTile(
title: Text(goalList.goalList[index].getName),
subtitle: Text('2020.07.16 ~ 2020.08.16'),
),
);
},
separatorBuilder: (context, index) {
return Divider();
},
);
}),
),
RaisedButton(
onPressed: () {
print(goalList.goalList[0]);
},
child: Text('List[0]'),
),
RaisedButton(
onPressed: () {
print(goalList.goalList[1]);
},
child: Text('List[1]'),
),
],
));
}
}
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => Index()),
ChangeNotifierProvider(create: (_) => Goal('None')),
ChangeNotifierProvider(create: (_) => GoalList())
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Todo App',
home: MainPage(),
),
);
}
}
class MainPage extends StatefulWidget {
#override
_MainPageState createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
var currentTab = [FirstPage(), SecondPage()];
#override
Widget build(BuildContext context) {
Index currentIndex = Provider.of<Index>(context);
Goal goal = Provider.of<Goal>(context);
return Scaffold(
body: IndexedStack(
index: currentIndex.currentIndex,
children: currentTab,
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: currentIndex.currentIndex,
onTap: (index) {
currentIndex.currentIndex = index;
},
type: BottomNavigationBarType.fixed,
// 하단바 아이콘 고정
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.add_circle), title: Text('Todo Create')),
BottomNavigationBarItem(
icon: Icon(Icons.format_list_bulleted),
title: Text('Todo List')),
BottomNavigationBarItem(
icon: Icon(Icons.calendar_today), title: Text('none')),
BottomNavigationBarItem(
icon: Icon(Icons.settings), title: Text('none')),
],
selectedItemColor: Colors.black87,
// 선택된 index 색깔
unselectedItemColor: Colors.black54,
// 선택안된 index 색깔
),
);
}
}

How to hide a floatingActionButton after insert data flutter?

I use sqflite for flutter database management. In particular, I would like the user to enter the data only once and therefore I would need to hide and disable the button only once the data has been entered. How can I do?
Home Page, where is the button
class Casa extends StatefulWidget {
static const routeName = '/';
#override
_CasaState createState() => _CasaState();
}
class _CasaState extends State<Casa> {
DataRepository _repository;
#override
void initState() {
super.initState();
_repository = SqlRepository();
}
#override
void dispose() async {
await _repository.closeDB();
super.dispose();
}
void getNewItem(BuildContext context) async {
Attivita newItem =
await Navigator.pushNamed<Attivita>(context, AddItemScreen.routeName);
if (newItem != null) {
await _repository.add(newItem);
setState(() {});
}
}
void switchAndUpdate(Attivita item) async {
await _repository.put(item.id, item);
setState(() {});
}
void delete(Attivita item) async {
await _repository.delete(item.id);
setState(() {});
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
backgroundColor: Colors.lightBlue[900],
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add, color: Colors.lightBlue[900],),
backgroundColor: Colors.white,
onPressed: () {
getNewItem(context);
},
),
body:
FutureBuilder<List<Attivita>>(
future: _repository.getAll(),
builder:
(BuildContext context, AsyncSnapshot<List<Attivita>> snapshot) {
return ListView.builder(
padding: EdgeInsets.all(8),
itemCount: snapshot.data == null ? 0 : snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return Dismissible(
key: UniqueKey(),
background: DecoratedBox(
decoration: BoxDecoration(color: Colors.red),
child: Align(
alignment: Alignment(-0.9, 00),
child: Icon(
Icons.delete,
color: Colors.white,
),
),
),
direction: DismissDirection.startToEnd,
onDismissed: (direction) {
Attivita item = snapshot.data[index];
snapshot.data.removeAt(index);
delete(item);
},
child: Card(
child: ListTile(
title: Text(snapshot.data[index].nome, style: TextStyle(color: Colors.lightBlue[900]),),
onTap: () {
Navigator.pushNamed(context, DettaglioScreen.routeName, arguments: snapshot.data[index]);
},
onLongPress: () {
switchAndUpdate(snapshot.data[index]);
},
),
),
);
},
);
},
)
),
);
}
}
so i have to add some details, because it is written that "it looks like your post is mostly code; please add some more details"
To check if user put so data you can use:
Use sharedPreferences and store bool value if user entered data.
On initState check if database contains data if yes it means user put some data and you can hide button.
I don't use Sqlite in flutter but I think you can use
List<Map<String, dynamic>> result;
result = await db.query(tableName);
isNotData = result.isEmpty;
Or something similar :) You can do it
Choose one way and store bool value eg. in bool isNotData
When you will have bool value about data you can write:
In _CasaState above initState: bool isNotData;
and in Scaffold in floatingActionButton property:
Scaffold(
appBar: AppBar(
title: Text('Material App Bar'),
),
floatingActionButton: isNotData
? FloatingActionButton(
onPressed: () {},
)
: null,
body: Center(
),
),
),

Flutter can't change route because undefined name context with PopupMenuButton how to solve?

I want to click an item menu (PopupMenuItem) and go to another route using Navigator.push but context is undefined inside the method.
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
final List<Choice> choices = const <Choice>[
const Choice(title: 'Settings', icon: Icons.settings),
const Choice(title: 'Log out', icon: Icons.exit_to_app),
];
#override
Widget build(BuildContext context) {
final title = 'MyTitle';
return MaterialApp(
title: title,
home: Scaffold(
appBar: AppBar(
title: Text(title),
actions: <Widget>[
PopupMenuButton<Choice>(
onSelected: onItemMenuPress,
itemBuilder: (BuildContext context) {
return choices.map((Choice choice) {
return PopupMenuItem<Choice>(
value: choice,
child: Row(
children: <Widget>[
Icon(
choice.icon,
),
Container(
width: 10.0,
),
Text(
choice.title,
),
],
));
}).toList();
},
),
],
),
body: Text("Hello world")
),
);
}
void onItemMenuPress(Choice choice) {
if (choice.title == 'Log out') {
print("Logout");
Navigator.push(context, MaterialPageRoute(builder: (context) => LogoutRoute()));
}
}
}
class Choice {
const Choice({this.title, this.icon});
final String title;
final IconData icon;
}
class LogoutRoute extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Logout"),
),
body: Center(
child: Text("Screen"),
),
);
}
}
I have tried to pass a context in onItemMenuPress in this way:
void onItemMenuPress(Choice choice, BuildContext context)
but:
onSelected: onItemMenuPress(context)
is not working.
Neither this approach works:
onSelected: (Choice c) { Navigator.push(context, MaterialPageRoute(builder: (context) => LogoutRoute())); }
I was following this tutorial:
https://medium.com/flutter-community/building-a-chat-app-with-flutter-and-firebase-from-scratch-9eaa7f41782e
and there is a snippet of his code (similar to mine) that seems to work for him:
https://github.com/duytq94/flutter-chat-demo/blob/master/lib/main.dart
I refer to line 235 (onSelected) and lines 199-205 (actual onItemMenuPress method)
How is it possible? How can I salve?
Thanks
Here you have :
MyApp <------ context
--> MaterialApp
(--> Navigator built within MaterialApp)
--> Scaffold
--> App Bar
--> ...
So when you're using the context to find the Navigator, you're using a context for the MyApp which isn't under the navigator.
so we can either make a new Stateless or Stateful Widget subclass to contain your Scaffold, as the build function within those will point at that level instead, or we can use a Builder and define the builder callback (which has a context pointing at the Builder) to return the Scaffold.
Working Code we created new subclass - HomeScreen :
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
final title = 'MyTitle';
return MaterialApp(
title: title,
home: HomeScreen(title),
);
}
}
class HomeScreen extends StatelessWidget {
final String title;
HomeScreen(this.title);
final List<Choice> choices = const <Choice>[
const Choice(title: 'Settings', icon: Icons.settings),
const Choice(title: 'Log out', icon: Icons.exit_to_app),
];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
actions: <Widget>[
PopupMenuButton<Choice>(
onSelected: (val) => onItemMenuPress(val, context),
itemBuilder: (BuildContext context) {
return choices.map((Choice choice) {
return PopupMenuItem<Choice>(
value: choice,
child: Row(
children: <Widget>[
Icon(
choice.icon,
),
Container(
width: 10.0,
),
Text(
choice.title,
),
],
));
}).toList();
},
),
],
),
body: Text("Hello world"));
}
void onItemMenuPress(Choice choice, BuildContext context) {
if (choice.title == 'Log out') {
print("Logout");
Navigator.push(
context, MaterialPageRoute(builder: (context) => LogoutRoute()));
}
}
}
class Choice {
const Choice({this.title, this.icon});
final String title;
final IconData icon;
}
class LogoutRoute extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Logout"),
),
body: Center(
child: Text("Screen"),
),
);
}
}
It happens because your flutter SDK and dark SDK is not working properly. you can solve this issues upgrading your flutter sdk. go to the terminal and type
flutter upgrade --force
after that your fluter sdk and dark sdk will be upgrade, after the installation complete you will be fine.

Flutter textformfield auto de-focus

This is the function I'm using to get a form displayed on my screen.
Form getNewLoanForm() {
return new Form(
child: new Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
new TextFormField(
decoration: new InputDecoration(labelText: 'Loan name'),
validator: (value) {
if (value.isEmpty) {
return 'Enter name';
} else {
return null;
}
},
onSaved: (value) => _loanName = value,
),
new Container(height: 16.0),
new RaisedButton(
child: new Text(
'ADD',
style: new TextStyle(color: Colors.white, fontSize: 17.0),
),
onPressed: addNewLoan,
color: Colors.blue,
)
],
),
);
}
Everything works fine up unit now. The problem starts when I add
final formKey = new GlobalKey<FormState>();
I declare this varial in class level. and use it in form.
return new Form(
key: formKey,
Like this and now the TextFormField starts to behave weirdly. Now if I select the text field it deselects itself.
Now keep in mind that this doesn't happen if I make this page my root page. But I'm pushing this page from my root page. If I make this page my root page the problem doesn't occur there.
Any idea what's wrong here?
Okay I'm putting my whole class
import 'package:flutter/material.dart';
import 'package:datetime_picker_formfield/datetime_picker_formfield.dart';
import 'package:intl/intl.dart';
class NewLoan extends StatelessWidget {
String _loanName;
String _dateCreated;
final formKey = new GlobalKey<FormState>();
void addNewLoan() {}
Form getNewLoanForm(BuildContext context) {
final dateFormat = DateFormat("dd/MM/yyyy");
return new Form(
// key: formKey,
child: new Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
new TextFormField(
decoration: new InputDecoration(labelText: 'Loan name'),
validator: (value) {
if (value.isEmpty) {
return 'Enter name';
} else {
_loanName = value;
return null;
}
},
),
new Container(height: 16.0),
DateTimePickerFormField(
decoration: new InputDecoration(labelText: 'Date'),
format: dateFormat,
dateOnly: true,
onChanged: (date) {
print('Selected date ${date.toString()}');
Scaffold
.of(context)
.showSnackBar(SnackBar(content: Text('$date')));
},
),
new Container(height: 16.0),
new RaisedButton(
child: new Text(
'ADD',
style: new TextStyle(color: Colors.white, fontSize: 17.0),
),
onPressed: addNewLoan,
color: Colors.blue,
)
],
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: new AppBar(
title: new Text('New Loan'),
),
body: new Container(
padding: new EdgeInsets.all(20.0),
child: getNewLoanForm(context),
),
);
}
}
My Root page
import 'dart:async';
import 'package:firebase/new_loan.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart';
import 'auth.dart';
import 'current_balance_page.dart';
import 'dart:io' show Platform;
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_database/ui/firebase_animated_list.dart';
class HomePage extends StatefulWidget {
HomePage({this.auth, this.onSignOut});
final BaseAuth auth;
final VoidCallback onSignOut;
#override
_HomePageState createState() => _HomePageState();
}
FirebaseApp app;
Future<FirebaseApp> firebaseApp() async {
final FirebaseApp app = await FirebaseApp.configure(
name: 'hisab-442a2',
options: Platform.isIOS
? const FirebaseOptions(
googleAppID: '1:18726312:ios:1b7829f2ac180d28',
gcmSenderID: '75461431231231291692',
databaseURL: 'https://hisab-44s2a2.firebaseio.com',
)
: const FirebaseOptions(
googleAppID: '1:297855924061:android:669871c998cc21bd',
apiKey: 'AIzaSyD_shO5mfO9lhy2TVWhfo1VUmARKlG4suk',
databaseURL: 'https://hisab-442a2.firebaseio.com',
),
);
return app;
}
enum Balancestatus { checking, found, noBalance }
class _HomePageState extends State<HomePage> {
Balancestatus status = Balancestatus.checking;
DatabaseReference _databaseRef;
#override
void initState() {
super.initState();
getDatabaseRef();
}
void getDatabaseRef() async {
app = await firebaseApp();
final FirebaseDatabase database = new FirebaseDatabase(app: app);
_databaseRef = database.reference();
_databaseRef.child('ccurrent_balance').once().then((DataSnapshot snapshot) {
print('Current balance ${snapshot.value}');
int balance = snapshot.value;
setState(() {
if (balance == null || balance == 0) {
status = Balancestatus.noBalance;
} else {
status = Balancestatus.found;
}
});
});
}
Future _signOut() async {
try {
await widget.auth.singOut();
widget.onSignOut();
} catch (e) {
print('Error signing out: $e');
}
}
void balanceSet() {
setState(() {
status = Balancestatus.checking;
});
}
#override
Widget build(BuildContext context) {
switch (status) {
case Balancestatus.checking:
return new WelcomePage(onSignOut: _signOut);
case Balancestatus.found:
// return new NewLoan();
return new LoanList(onSignOut: _signOut);
case Balancestatus.noBalance:
return CurrentBalancePage(
databaseRef: _databaseRef,
balanceSet: balanceSet,
);
default:
return new WelcomePage(onSignOut: _signOut);
}
}
}
class LoanList extends StatelessWidget {
final VoidCallback onSignOut;
LoanList({this.onSignOut});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: new AppBar(
title: Text('Loans'),
actions: <Widget>[
new FlatButton(
child: new Text(
'Logout',
style: new TextStyle(fontSize: 17.0, color: Colors.white),
),
onPressed: onSignOut,
)
],
),
body: new Container(
padding: EdgeInsets.all(20.0),
alignment: Alignment.bottomCenter,
child: new RaisedButton(
child: new Text(
'New Loan',
style: new TextStyle(color: Colors.white, fontSize: 17.0),
),
onPressed: (){
Navigator.push(context, MaterialPageRoute(builder: (context) => NewLoan()));
},
color: Colors.blue,
),
),
);
}
void addNewLoan() {
print('Add new Loan');
}
}
class WelcomePage extends StatelessWidget {
final VoidCallback onSignOut;
WelcomePage({this.onSignOut});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: new AppBar(
title: new Text('Welcome'),
actions: <Widget>[
new FlatButton(
child: new Text(
'Logout',
style: new TextStyle(fontSize: 17.0, color: Colors.white),
),
onPressed: onSignOut,
)
],
),
body: new Container(
child: new Center(
child: new Text(
'Checking',
style: new TextStyle(fontSize: 32.0),
),
),
),
);
}
}

Resources