I'm a newbie of Flutter. I've written some codes which enable users to login or register with their own account and password. But when I want to add data to lists such as Username, Account and ID, I always get this error : "NoSuchMethodError: The method 'add' was called on null.". I've read some similar questions people asked. Most of them got the error just because they didn't initialize the List. Unlike them, I've initialized every List, but I still got this error continually. Please help me with the problem, tks.
The function which caused the error:
Future Register() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
Username.add(_RtextFieldUsername.value.text.toString());
Account.add(_RtextFieldAccount.value.text.toString());
ID.add(_RtextFieldID.value.text.toString());
await prefs.setStringList(_StorageAccount, Account);
await prefs.setStringList(_StorageID, ID);
await prefs.setStringList(_StorageUsername, Username);
}
Entire codes:
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'Uhome.dart';
import 'Thome.dart';
class ProfilePage extends StatefulWidget{
List<String> Username = List();
List<String> Account = List();
List<String> ID = List();
ProfilePage({this.Username, this.Account, this.ID});
#override
_ProfilePageState createState() => _ProfilePageState(Username, Account, ID);
}
class _ProfilePageState extends State<ProfilePage>{
List<String> Username = List();
List<String> Account = List();
List<String> ID = List();
_ProfilePageState(this.Username, this.Account, this.ID);
int _currentIndex = 2;
final _Pages = <Widget>[
UniversityPage(),
TransportationPage(),
ProfilePage(),
];
var _LtextFieldAccount = new TextEditingController();
var _LtextFieldID = new TextEditingController();
final _StorageUsername = 'Username';
final _StorageAccount = 'Account';
final _StorageID = 'ID';
String LoginedUsername = '';
Future Login() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
bool checked = false;
String InsertAccount = _LtextFieldAccount.value.text.toString();
String InsertID = _LtextFieldID.value.text.toString();
List<String> GetAccountList = (prefs.getStringList(_StorageAccount) ?? List<String>());
List<String> GetIDList = (prefs.getStringList(_StorageID) ?? List<String>());
for(int i = 0 ; i < GetAccountList.length ; i++){
if(GetAccountList[i] == InsertAccount && GetIDList[i] == InsertID){
List<String> GetUsernameList = (prefs.getStringList(_StorageUsername) ?? List<String>());
checked = true;
LoginedUsername = GetUsernameList[i];
break;
}
}
if(checked == true){
print('Succeed');// Navigate to profile page
}
else{
Alert(context);// stay at the same page
}
}
void Alert(BuildContext context) {
AlertDialog dialog = AlertDialog(
backgroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(15)),
),
content: Container(
padding: EdgeInsets.only(left: 5, top: 5, bottom: 5),
child: Row(
children: <Widget>[
Icon(
Icons.warning,
color: Colors.black54,
size: 30,
),
Padding(padding: EdgeInsets.only(right: 10)),
Text("帳號或密碼輸入錯誤", style: TextStyle(color: Colors.black, fontSize: 20,),
),
],
),
),
actions: <Widget>[
FlatButton(
onPressed: () {
Navigator.pop(context, true);
},
child: Text("確定", style: TextStyle(color: Colors.blueAccent),),
),
],
);
showDialog(
barrierDismissible: false,
context: context,
builder: (BuildContext context) => dialog,
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
Container(
height: double.infinity,
width: double.infinity,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color(0xFF73AEF5),
Color(0xFF61A4F1),
Color(0xFF478DE0),
Color(0xFF398AE5),
],
stops: [0.1, 0.4, 0.7, 0.9],
)
),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(height: 10,),
Icon(Icons.account_circle, size: 150.0,),
SizedBox(height: 30),
Container(
width: 300,
child: Theme(
data: ThemeData(
primaryColor: Colors.white,
primaryColorDark: Colors.yellowAccent,
),
child: TextField(
controller: _LtextFieldAccount,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: '請輸入帳號',
prefixIcon: const Icon(Icons.person)
),
)
),
),
SizedBox(height: 20),
Container(
width: 300,
child: Theme(
data: ThemeData(
primaryColor: Colors.white,
primaryColorDark: Colors.yellowAccent,
),
child: TextField(
controller: _LtextFieldID,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: '請輸入密碼',
prefixIcon: const Icon(Icons.lock)
),
)
),
),
SizedBox(height: 30),
RaisedButton(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(25.0)),
elevation: 4.0,
color: Colors.white,
child: Container(
padding: EdgeInsets.only(left: 10, right: 10, top: 10, bottom: 10),
child: Text('登入', style: TextStyle(fontSize: 25, color: Colors.blueAccent),),
),
onPressed: Login,
),
SizedBox(height: 20),
RaisedButton(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(25.0)),
elevation: 4.0,
color: Colors.white,
child: Container(
padding: EdgeInsets.only(left: 10, right: 10, top: 10, bottom: 10),
child: Text('新用戶註冊', style: TextStyle(fontSize: 25, color: Colors.blueAccent),),
),
onPressed: (){
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => RegisterPage(Username: Username, Account: Account, ID: ID,)
));
}
)
],
),
),
),
],
),
bottomNavigationBar: BottomNavigationBar(
onTap: onTabTapped,
currentIndex: _currentIndex,
// this will be set when a new tab is tapped
items: [
new BottomNavigationBarItem(
icon: new Icon(Icons.school),
title: new Text('大學'),
),
new BottomNavigationBarItem(
icon: new Icon(Icons.directions_subway),
title: new Text('交通'),
),
new BottomNavigationBarItem(
icon: new Icon(Icons.person),
title: new Text('個人'),
)
],
),
);
}
void onTabTapped(int index){
setState(() {
_currentIndex = index;
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) => _Pages[index],
transitionDuration: Duration(seconds: 0),
),
);
});
}
}
// LoginPage-----------------------------------------------------------------------------------------------------------------------------------------------------------------
class RegisterPage extends StatefulWidget{
List<String> Username = List();
List<String> Account = List();
List<String> ID = List();
RegisterPage({this.Username, this.Account, this.ID});
RegisterPageState createState() => RegisterPageState(Username, Account, ID);
}
class RegisterPageState extends State<RegisterPage>{
List<String> Username = List();
List<String> Account = List();
List<String> ID = List();
RegisterPageState(this.Username, this.Account, this.ID);
int _currentIndex = 2;
final _Pages = <Widget>[
UniversityPage(),
TransportationPage(),
ProfilePage(),
];
var _RtextFieldUsername = new TextEditingController();
var _RtextFieldAccount = new TextEditingController();
var _RtextFieldID = new TextEditingController();
final _StorageUsername = 'Username';
final _StorageAccount = 'Account';
final _StorageID = 'ID';
// register & store data
Future Register() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
Username.add(_RtextFieldUsername.value.text.toString());
Account.add(_RtextFieldAccount.value.text.toString());
ID.add(_RtextFieldID.value.text.toString());
await prefs.setStringList(_StorageAccount, Account);
await prefs.setStringList(_StorageID, ID);
await prefs.setStringList(_StorageUsername, Username);
}
void Alert(BuildContext context) {
AlertDialog dialog = AlertDialog(
backgroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(15)),
),
content: Container(
padding: EdgeInsets.only(left: 5, top: 5, bottom: 5),
child: Row(
children: <Widget>[
Icon(
Icons.check,
color: Colors.black54,
size: 30,
),
Padding(padding: EdgeInsets.only(right: 10)),
Text("註冊成功! =D\n請重新登入", style: TextStyle(color: Colors.black, fontSize: 20,),
),
],
),
),
actions: <Widget>[
FlatButton(
onPressed: () {
Navigator.pop(context, true);
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => ProfilePage(Username: Username, Account: Account, ID: ID,)
));
},
child: Text("確定", style: TextStyle(color: Colors.blueAccent),),
),
],
);
showDialog(
barrierDismissible: false,
context: context,
builder: (BuildContext context) => dialog,
);
}
void RegisterAlert(BuildContext context, int num) {
List<String> AlertText = ['欄位不可為空', '帳號需至少8個字元', '密碼需至少8個字元'];
AlertDialog dialog = AlertDialog(
backgroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(15)),
),
content: Container(
padding: EdgeInsets.only(left: 5, top: 5, bottom: 5),
child: Row(
children: <Widget>[
Icon(
Icons.warning,
color: Colors.black54,
size: 30,
),
Padding(padding: EdgeInsets.only(right: 10)),
Text(AlertText[num], style: TextStyle(color: Colors.black, fontSize: 20,),
),
],
),
),
actions: <Widget>[
FlatButton(
onPressed: () {
Navigator.pop(context, true);
},
child: Text("確定", style: TextStyle(color: Colors.blueAccent),),
),
],
);
showDialog(
barrierDismissible: false,
context: context,
builder: (BuildContext context) => dialog,
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
Container(
height: double.infinity,
width: double.infinity,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color(0xFF73AEF5),
Color(0xFF61A4F1),
Color(0xFF478DE0),
Color(0xFF398AE5),
],
stops: [0.1, 0.4, 0.7, 0.9],
)
),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(height: 10,),
Icon(Icons.person_add, size: 150.0,),
SizedBox(height: 30),
Container(
width: 300,
child: Theme(
data: ThemeData(
primaryColor: Colors.white,
primaryColorDark: Colors.yellowAccent,
),
child: TextField(
controller: _RtextFieldUsername,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: '請輸入用戶名',
prefixIcon: const Icon(Icons.face)
),
)
),
),
SizedBox(height: 20),
Container(
width: 300,
child: Theme(
data: ThemeData(
primaryColor: Colors.white,
primaryColorDark: Colors.yellowAccent,
),
child: TextField(
controller: _RtextFieldAccount,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: '請輸入註冊帳號',
prefixIcon: const Icon(Icons.person)
),
)
),
),
SizedBox(height: 20),
Container(
width: 300,
child: Theme(
data: ThemeData(
primaryColor: Colors.white,
primaryColorDark: Colors.yellowAccent,
),
child: TextField(
controller: _RtextFieldID,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: '請輸入註冊密碼',
prefixIcon: const Icon(Icons.lock)
),
)
),
),
SizedBox(height: 30),
RaisedButton(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(25.0)),
elevation: 4.0,
color: Colors.white,
child: Container(
padding: EdgeInsets.only(left: 10, right: 10, top: 10, bottom: 10),
child: Text('註冊', style: TextStyle(fontSize: 25, color: Colors.blueAccent),),
),
onPressed: (){
if(_RtextFieldUsername.value.text.toString() == '' || _RtextFieldAccount.value.text.toString() == '' || _RtextFieldID.value.text.toString() == '' ){
RegisterAlert(context, 0);
}
else if(_RtextFieldAccount.value.text.toString().length < 8){
RegisterAlert(context, 1);
}
else if(_RtextFieldID.value.text.toString().length < 8){
RegisterAlert(context, 2);
}
else{
Register();
Alert(context);
}
},
),
],
),
),
),
],
),
bottomNavigationBar: BottomNavigationBar(
onTap: onTabTapped,
currentIndex: _currentIndex,
// this will be set when a new tab is tapped
items: [
new BottomNavigationBarItem(
icon: new Icon(Icons.school),
title: new Text('大學'),
),
new BottomNavigationBarItem(
icon: new Icon(Icons.directions_subway),
title: new Text('交通'),
),
new BottomNavigationBarItem(
icon: new Icon(Icons.person),
title: new Text('個人'),
)
],
),
);
}
void onTabTapped(int index){
setState(() {
_currentIndex = index;
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) => _Pages[index],
transitionDuration: Duration(seconds: 0),
),
);
});
}
}
Error message:
E/flutter (20665): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: NoSuchMethodError: The method 'add' was called on null.
E/flutter (20665): Receiver: null
E/flutter (20665): Tried calling: add("username")
E/flutter (20665): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
E/flutter (20665): #1 RegisterPageState.Register (package:roadtouniversity/profile.dart:281:14)
E/flutter (20665): <asynchronous suspension>
E/flutter (20665): #2 RegisterPageState.build.<anonymous closure> (package:roadtouniversity/profile.dart:473:25)
E/flutter (20665): #3 _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:779:19)
E/flutter (20665): #4 _InkResponseState.build.<anonymous closure> (package:flutter/src/material/ink_well.dart:862:36)
E/flutter (20665): #5 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:182:24)
E/flutter (20665): #6 TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:504:11)
E/flutter (20665): #7 BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:282:5)
E/flutter (20665): #8 BaseTapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:217:7)
E/flutter (20665): #9 PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:475:9)
E/flutter (20665): #10 PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:76:12)
E/flutter (20665): #11 PointerRouter._dispatchEventToRoutes.<anonymous closure> (package:flutter/src/gestures/pointer_router.dart:122:9)
E/flutter (20665): #12 _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:379:8)
E/flutter (20665): #13 PointerRouter._dispatchEventToRoutes (package:flutter/src/gestures/pointer_router.dart:120:18)
E/flutter (20665): #14 PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:106:7)
E/flutter (20665): #15 GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:218:19)
E/flutter (20665): #16 GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:198:22)
E/flutter (20665): #17 GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:156:7)
E/flutter (20665): #18 GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:102:7)
E/flutter (20665): #19 GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:86:7)
E/flutter (20665): #20 _rootRunUnary (dart:async/zone.dart:1196:13)
E/flutter (20665): #21 _CustomZone.runUnary (dart:async/zone.dart:1085:19)
E/flutter (20665): #22 _CustomZone.runUnaryGuarded (dart:async/zone.dart:987:7)
E/flutter (20665): #23 _invoke1 (dart:ui/hooks.dart:275:10)
E/flutter (20665): #24 _dispatchPointerDataPacket (dart:ui/hooks.dart:184:5)
E/flutter (20665):
You can copy paste run full code below
Step 1: Call ProfilePage with init value
home: ProfilePage(
Username: [],
Account: [],
ID: [],
),
Step 2: You do not need to init List<String> again
class ProfilePage extends StatefulWidget {
List<String> Username;
List<String> Account;
List<String> ID;
...
class _ProfilePageState extends State<ProfilePage> {
List<String> Username;
List<String> Account;
List<String> ID;
...
class RegisterPage extends StatefulWidget {
List<String> Username;
List<String> Account;
List<String> ID;
...
class RegisterPageState extends State<RegisterPage> {
List<String> Username;
List<String> Account;
List<String> ID;
...
Step 3: Use SingleChildScrollView to avoid overflow
child: SingleChildScrollView(
child: Center(
working demo
full code
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class ProfilePage extends StatefulWidget {
List<String> Username;
List<String> Account;
List<String> ID;
ProfilePage({this.Username, this.Account, this.ID});
#override
_ProfilePageState createState() => _ProfilePageState(Username, Account, ID);
}
class _ProfilePageState extends State<ProfilePage> {
List<String> Username;
List<String> Account;
List<String> ID;
_ProfilePageState(this.Username, this.Account, this.ID);
int _currentIndex = 2;
final _Pages = <Widget>[
UniversityPage(),
TransportationPage(),
ProfilePage(),
];
var _LtextFieldAccount = new TextEditingController();
var _LtextFieldID = new TextEditingController();
final _StorageUsername = 'Username';
final _StorageAccount = 'Account';
final _StorageID = 'ID';
String LoginedUsername = '';
Future Login() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
bool checked = false;
String InsertAccount = _LtextFieldAccount.value.text.toString();
String InsertID = _LtextFieldID.value.text.toString();
List<String> GetAccountList =
(prefs.getStringList(_StorageAccount) ?? List<String>());
List<String> GetIDList =
(prefs.getStringList(_StorageID) ?? List<String>());
for (int i = 0; i < GetAccountList.length; i++) {
if (GetAccountList[i] == InsertAccount && GetIDList[i] == InsertID) {
List<String> GetUsernameList =
(prefs.getStringList(_StorageUsername) ?? List<String>());
checked = true;
LoginedUsername = GetUsernameList[i];
break;
}
}
if (checked == true) {
print('Succeed'); // Navigate to profile page
} else {
Alert(context); // stay at the same page
}
}
void Alert(BuildContext context) {
AlertDialog dialog = AlertDialog(
backgroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(15)),
),
content: Container(
padding: EdgeInsets.only(left: 5, top: 5, bottom: 5),
child: Row(
children: <Widget>[
Icon(
Icons.warning,
color: Colors.black54,
size: 30,
),
Padding(padding: EdgeInsets.only(right: 10)),
Text(
"帳號或密碼輸入錯誤",
style: TextStyle(
color: Colors.black,
fontSize: 20,
),
),
],
),
),
actions: <Widget>[
FlatButton(
onPressed: () {
Navigator.pop(context, true);
},
child: Text(
"確定",
style: TextStyle(color: Colors.blueAccent),
),
),
],
);
showDialog(
barrierDismissible: false,
context: context,
builder: (BuildContext context) => dialog,
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
Container(
height: double.infinity,
width: double.infinity,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color(0xFF73AEF5),
Color(0xFF61A4F1),
Color(0xFF478DE0),
Color(0xFF398AE5),
],
stops: [0.1, 0.4, 0.7, 0.9],
)),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(
height: 10,
),
Icon(
Icons.account_circle,
size: 150.0,
),
SizedBox(height: 30),
Container(
width: 300,
child: Theme(
data: ThemeData(
primaryColor: Colors.white,
primaryColorDark: Colors.yellowAccent,
),
child: TextField(
controller: _LtextFieldAccount,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: '請輸入帳號',
prefixIcon: const Icon(Icons.person)),
)),
),
SizedBox(height: 20),
Container(
width: 300,
child: Theme(
data: ThemeData(
primaryColor: Colors.white,
primaryColorDark: Colors.yellowAccent,
),
child: TextField(
controller: _LtextFieldID,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: '請輸入密碼',
prefixIcon: const Icon(Icons.lock)),
)),
),
SizedBox(height: 30),
RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25.0)),
elevation: 4.0,
color: Colors.white,
child: Container(
padding: EdgeInsets.only(
left: 10, right: 10, top: 10, bottom: 10),
child: Text(
'登入',
style:
TextStyle(fontSize: 25, color: Colors.blueAccent),
),
),
onPressed: Login,
),
SizedBox(height: 20),
RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25.0)),
elevation: 4.0,
color: Colors.white,
child: Container(
padding: EdgeInsets.only(
left: 10, right: 10, top: 10, bottom: 10),
child: Text(
'新用戶註冊',
style:
TextStyle(fontSize: 25, color: Colors.blueAccent),
),
),
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => RegisterPage(
Username: Username,
Account: Account,
ID: ID,
)));
})
],
),
),
),
],
),
bottomNavigationBar: BottomNavigationBar(
onTap: onTabTapped,
currentIndex: _currentIndex,
// this will be set when a new tab is tapped
items: [
new BottomNavigationBarItem(
icon: new Icon(Icons.school),
title: new Text('大學'),
),
new BottomNavigationBarItem(
icon: new Icon(Icons.directions_subway),
title: new Text('交通'),
),
new BottomNavigationBarItem(
icon: new Icon(Icons.person),
title: new Text('個人'),
)
],
),
);
}
void onTabTapped(int index) {
setState(() {
_currentIndex = index;
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) => _Pages[index],
transitionDuration: Duration(seconds: 0),
),
);
});
}
}
// LoginPage-----------------------------------------------------------------------------------------------------------------------------------------------------------------
class RegisterPage extends StatefulWidget {
List<String> Username;
List<String> Account;
List<String> ID;
RegisterPage({this.Username, this.Account, this.ID});
RegisterPageState createState() => RegisterPageState(Username, Account, ID);
}
class RegisterPageState extends State<RegisterPage> {
List<String> Username;
List<String> Account;
List<String> ID;
RegisterPageState(this.Username, this.Account, this.ID);
int _currentIndex = 2;
final _Pages = <Widget>[
UniversityPage(),
TransportationPage(),
ProfilePage(),
];
var _RtextFieldUsername = new TextEditingController();
var _RtextFieldAccount = new TextEditingController();
var _RtextFieldID = new TextEditingController();
final _StorageUsername = 'Username';
final _StorageAccount = 'Account';
final _StorageID = 'ID';
// register & store data
Future Register() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
Username.add(_RtextFieldUsername.value.text.toString());
Account.add(_RtextFieldAccount.value.text.toString());
ID.add(_RtextFieldID.value.text.toString());
await prefs.setStringList(_StorageAccount, Account);
await prefs.setStringList(_StorageID, ID);
await prefs.setStringList(_StorageUsername, Username);
}
void Alert(BuildContext context) {
AlertDialog dialog = AlertDialog(
backgroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(15)),
),
content: Container(
padding: EdgeInsets.only(left: 5, top: 5, bottom: 5),
child: Row(
children: <Widget>[
Icon(
Icons.check,
color: Colors.black54,
size: 30,
),
Padding(padding: EdgeInsets.only(right: 10)),
Text(
"註冊成功! =D\n請重新登入",
style: TextStyle(
color: Colors.black,
fontSize: 20,
),
),
],
),
),
actions: <Widget>[
FlatButton(
onPressed: () {
Navigator.pop(context, true);
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => ProfilePage(
Username: Username,
Account: Account,
ID: ID,
)));
},
child: Text(
"確定",
style: TextStyle(color: Colors.blueAccent),
),
),
],
);
showDialog(
barrierDismissible: false,
context: context,
builder: (BuildContext context) => dialog,
);
}
void RegisterAlert(BuildContext context, int num) {
List<String> AlertText = ['欄位不可為空', '帳號需至少8個字元', '密碼需至少8個字元'];
AlertDialog dialog = AlertDialog(
backgroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(15)),
),
content: Container(
padding: EdgeInsets.only(left: 5, top: 5, bottom: 5),
child: Row(
children: <Widget>[
Icon(
Icons.warning,
color: Colors.black54,
size: 30,
),
Padding(padding: EdgeInsets.only(right: 10)),
Text(
AlertText[num],
style: TextStyle(
color: Colors.black,
fontSize: 20,
),
),
],
),
),
actions: <Widget>[
FlatButton(
onPressed: () {
Navigator.pop(context, true);
},
child: Text(
"確定",
style: TextStyle(color: Colors.blueAccent),
),
),
],
);
showDialog(
barrierDismissible: false,
context: context,
builder: (BuildContext context) => dialog,
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
Container(
height: double.infinity,
width: double.infinity,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color(0xFF73AEF5),
Color(0xFF61A4F1),
Color(0xFF478DE0),
Color(0xFF398AE5),
],
stops: [0.1, 0.4, 0.7, 0.9],
)),
child: SingleChildScrollView(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(
height: 10,
),
Icon(
Icons.person_add,
size: 150.0,
),
SizedBox(height: 30),
Container(
width: 300,
child: Theme(
data: ThemeData(
primaryColor: Colors.white,
primaryColorDark: Colors.yellowAccent,
),
child: TextField(
controller: _RtextFieldUsername,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: '請輸入用戶名',
prefixIcon: const Icon(Icons.face)),
)),
),
SizedBox(height: 20),
Container(
width: 300,
child: Theme(
data: ThemeData(
primaryColor: Colors.white,
primaryColorDark: Colors.yellowAccent,
),
child: TextField(
controller: _RtextFieldAccount,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: '請輸入註冊帳號',
prefixIcon: const Icon(Icons.person)),
)),
),
SizedBox(height: 20),
Container(
width: 300,
child: Theme(
data: ThemeData(
primaryColor: Colors.white,
primaryColorDark: Colors.yellowAccent,
),
child: TextField(
controller: _RtextFieldID,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: '請輸入註冊密碼',
prefixIcon: const Icon(Icons.lock)),
)),
),
SizedBox(height: 30),
RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25.0)),
elevation: 4.0,
color: Colors.white,
child: Container(
padding: EdgeInsets.only(
left: 10, right: 10, top: 10, bottom: 10),
child: Text(
'註冊',
style:
TextStyle(fontSize: 25, color: Colors.blueAccent),
),
),
onPressed: () {
if (_RtextFieldUsername.value.text.toString() == '' ||
_RtextFieldAccount.value.text.toString() == '' ||
_RtextFieldID.value.text.toString() == '') {
RegisterAlert(context, 0);
} else if (_RtextFieldAccount.value.text
.toString()
.length <
8) {
RegisterAlert(context, 1);
} else if (_RtextFieldID.value.text.toString().length <
8) {
RegisterAlert(context, 2);
} else {
Register();
Alert(context);
}
},
),
],
),
),
),
),
],
),
bottomNavigationBar: BottomNavigationBar(
onTap: onTabTapped,
currentIndex: _currentIndex,
// this will be set when a new tab is tapped
items: [
new BottomNavigationBarItem(
icon: new Icon(Icons.school),
title: new Text('大學'),
),
new BottomNavigationBarItem(
icon: new Icon(Icons.directions_subway),
title: new Text('交通'),
),
new BottomNavigationBarItem(
icon: new Icon(Icons.person),
title: new Text('個人'),
)
],
),
);
}
void onTabTapped(int index) {
setState(() {
_currentIndex = index;
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) => _Pages[index],
transitionDuration: Duration(seconds: 0),
),
);
});
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: ProfilePage(
Username: [],
Account: [],
ID: [],
),
);
}
}
class UniversityPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Text("UniversityPage");
}
}
class TransportationPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Text("TransportationPage");
}
}
You're passing the lists from one class to another
ProfilePage > _ProfilePageState > RegisterPage > RegisterPageState
But that doesn't mean at the beggining the lists cannot be null.
class ProfilePage extends StatefulWidget{
List<String> Username = List();
List<String> Account = List();
List<String> ID = List();
ProfilePage({this.Username, this.Account, this.ID});
#override
_ProfilePageState createState() => _ProfilePageState(Username, Account, ID);
}
Initializing them as List but calling them in the constructor means that they will be override with the value of the constructor. If you start with ProfilePage(Username: null, Account: null, ID: null) or just call it ProfilePage() then those attributes are null, despite the value you gave them at the beggining. You have to be sure that when the class ProfilePage is created the attributes passed to aren't null, or else the whole logic will be null
Also just as others point out you don't need to init them in the StatefulWidget and State
class RegisterPage extends StatefulWidget{
List<String> Username = List();
List<String> Account = List();
List<String> ID = List();
RegisterPage({this.Username, this.Account, this.ID});
RegisterPageState createState() => RegisterPageState(Username, Account, ID);
}
class RegisterPageState extends State<RegisterPage>{
List<String> Username = List(); //This is pointless
List<String> Account = List(); //This is pointless
List<String> ID = List(); //This is pointless
...
}
If you want to use/modify the one you just pass from the previous page just use them like this
class RegisterPage extends StatefulWidget{
List<String> Username = List(); //you wanted to use this
List<String> Account = List(); //you wanted to use this
List<String> ID = List(); //you wanted to use this
RegisterPage({this.Username, this.Account, this.ID});
RegisterPageState createState() => RegisterPageState(); //no need to pass the parameters
}
class RegisterPageState extends State<RegisterPage>{
Future Register() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
widget.Username.add(_RtextFieldUsername.value.text.toString());
widget.Account.add(_RtextFieldAccount.value.text.toString());
widget.ID.add(_RtextFieldID.value.text.toString());
/*
widget.value let you use the objects/variables defined in the StatefulWidget
so you don't need to create new ones in the State
*/
await prefs.setStringList(_StorageAccount, Account);
await prefs.setStringList(_StorageID, ID);
await prefs.setStringList(_StorageUsername, Username);
}
....
}
Related
I have defined a variable named data in the Controller class. I am getting the error I mentioned above in the fillWordlist method. I created listview.builder in the historyWordList method in the view class. but the list does not appear on the screen and I am getting this error. 'List<Word?>' is not a subtype of type 'List' of 'val'E/flutter (29035): #0 RxObjectMixin.value= (package:get/get_rx/src/rx_types/rx_core/rx_impl .darts)
E/flutter (29035): #1 WordController.fillWordList (package:your_research_translation/controller/word_controller.dart:56:10)'
Controller.class
class WordController extends GetxController {
TextEditingController controllerInput1 = TextEditingController();
TextEditingController controllerInput2 = TextEditingController();
RxBool active2 = false.obs;
final translator = GoogleTranslator();
RxList data = <Word>[].obs;
#override
void onInit() {
fillWordList();
super.onInit();
}
onClickIconButtonFavori() {
if (controllerInput1.text.isNotEmpty && controllerInput2.text.isNotEmpty) {
addNote();
clear();
}
}
showText() {
if (active2.value == true) {
return;
}
active2.toggle();
}
ekle(Word word) async {
var val = await WordRepo().add(word);
showDilog("Kayıt Başarılı");
update();
return val;
}
updateWord(Word word) async {
var val = await WordRepo().update(word);
showDilog("Kayıt Başarılı");
return val;
}
deleteWord(int? id) async {
var val = await WordRepo().deleteById(id!);
return val;
}
fillWordList() async {
data.value = await WordRepo().getAll();
}
translateLanguage(String newValue) async {
if (newValue == null || newValue.length == 0) {
return;
}
List list = ["I", "i"];
if (newValue.length == 1 && !list.contains(newValue)) {
return;
}
var translate = await translator.translate(newValue, from: 'en', to: 'tr');
controllerInput2.text = translate.toString();
return translate;
}
showDilog(String message) {
Get.defaultDialog(title: "Bilgi", middleText: message);
}
addNote() async {
var word =
Word(wordEn: controllerInput1.text, wordTr: controllerInput2.text);
await ekle(word);
fillWordList();
}
clear() {
controllerInput2.clear();
controllerInput1.clear();
}
updateNote() async {
var word =
Word(wordEn: controllerInput1.text, wordTr: controllerInput2.text);
await updateWord(word);
await fillWordList();
update();
}
}
view class: Main_page.dart
class MainPage extends StatelessWidget {
String _firstLanguage = "English";
String _secondLanguage = "Turkish";
WordController controller = Get.put(WordController());
final _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Scaffold(
drawer: _drawer,
backgroundColor: Colors.grey.shade300,
appBar: _appbar,
body: _bodyScaffold,
floatingActionButton: _floattingActionButton,
);
}
SingleChildScrollView get _bodyScaffold {
return SingleChildScrollView(
child: Column(
children: [
chooseLanguage,
translateTextView,
//futureBuilder,
],
),
);
}
AppBar get _appbar {
return AppBar(
backgroundColor: Colors.blueAccent,
centerTitle: true,
title: Text("TRANSLATE"),
elevation: 0.0,
);
}
get chooseLanguage => Container(
height: Get.height / 12.0,
decoration: buildBoxDecoration,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
firstChooseLanguage,
changeLanguageButton,
secondChooseLanguage,
],
),
);
get buildBoxDecoration {
return BoxDecoration(
color: Colors.white,
border: Border(
bottom: BorderSide(
width: 3.5,
color: Colors.grey,
),
),
);
}
get translateTextView => Column(
children: [
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8.0)),
),
margin: EdgeInsets.only(left: 2.0, right: 2.0, top: 2.0),
child: _formTextField,
),
Obx(
() => Container(
height: controller.active2 == true
? Get.height / 2.3
: Get.height / 1.6,
child: historyWordList,
),
)
],
);
Widget get historyWordList {
return ListView.builder(
itemCount: controller.data.length,
itemBuilder: (context, index) {
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(5.0)),
),
margin: EdgeInsets.only(left: 8.0, right: 8.0, top: 0.8),
child: Container(
color: Colors.white30,
padding: EdgeInsets.only(left: 8.0, top: 8.0, bottom: 8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Obx(()=>Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
firstText(controller.data[index].value),
secondText(controller.data[index].value),
],
)),
historyIconbutton,
],
),
),
);
},
);
}
get _formTextField {
return Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
color: Colors.white30,
height: Get.height / 6.0,
padding: EdgeInsets.only(left: 16.0, top: 8.0, bottom: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
textFormFieldEntr, //one textfield
favoriIconButton,
],
),
),
textFormField, //burası kapandı // second
],
),
);
}
get textFormFieldEntr {
return Flexible(
child: Container(
height: Get.height / 5.2,
child: TextFormField(
readOnly: true, //sadece okuma
onTap: () {
showMaterialBanner();
},
controller: controller.controllerInput1,
onChanged: (text) {
if (text.isEmpty) {
controller.active2(false);
} else {
controller.active2(true);
}
},
maxLines: 6,
decoration: InputDecoration(
hintText: "Enter",
contentPadding: const EdgeInsets.symmetric(vertical: 5.0),
),
),
),
);
}
void showMaterialBanner() {
ScaffoldMessenger.of(Get.context!).showMaterialBanner(MaterialBanner(
backgroundColor: Colors.white,
content: Padding(
padding: const EdgeInsets.only(top: 40.0),
child: Column(
children: [
TextFormField(
controller: controller.controllerInput1,
maxLines: 7,
onChanged: (text) {
controller.translateLanguage(text);
if (text.isNotEmpty) {
controller.showText();
}
// controller.showText();
},
decoration: InputDecoration(
suffixIcon: IconButton(
onPressed: () {
if (controller.controllerInput1.text.length > 0) {
controller.clear();
} else {
controller.clear();
closeBanner();
}
},
icon: Icon(Icons.clear),
),
contentPadding: const EdgeInsets.symmetric(vertical: 5.0),
),
),
SizedBox(height: Get.height / 6.0),
TextFormField(
controller: controller.controllerInput2,
maxLines: 7,
onTap: () {
if (controller.controllerInput1.text.isEmpty) {
controller.clear();
} else {
controller.addNote();
}
closeBanner();
},
decoration: InputDecoration(
contentPadding: const EdgeInsets.symmetric(vertical: 5.0),
),
),
],
),
),
actions: [
IconButton(
onPressed: () {
closeBanner();
},
icon: Icon(null),
),
]));
}
void closeBanner() {
ScaffoldMessenger.of(Get.context!).hideCurrentMaterialBanner();
}
get textFormField {
return Obx(() {
return Container(
child: Visibility(
visible: controller.active2.value, //false
child: Container(
color: Colors.white30,
height: Get.height / 5.2,
padding:
EdgeInsets.only(left: 16.0, right: 42.0, top: 8.0, bottom: 8.0),
child: TextFormField(
readOnly: true,
controller: controller.controllerInput2,
maxLines: 6,
decoration: InputDecoration(
contentPadding: const EdgeInsets.symmetric(vertical: 5.0),
),
),
),
),
);
});
}
IconButton get historyIconbutton {
return IconButton(
onPressed: () {},
icon: Icon(Icons.history),
iconSize: 30.0,
);
}
Text firstText(Word word) {
return Text(
"İngilizce: ${word.wordEn ?? ""}",
style: TextStyle(
fontWeight: FontWeight.w600,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
);
}
get changeLanguageButton {
return Material(
color: Colors.white,
child: IconButton(
icon: Icon(
Icons.wifi_protected_setup_rounded,
color: Colors.indigo,
size: 30.0,
),
onPressed: () {},
),
);
}
get secondChooseLanguage {
return Expanded(
child: Material(
color: Colors.white,
child: InkWell(
onTap: () {},
child: Center(
child: Text(
this._secondLanguage,
style: TextStyle(
color: Colors.blue[600],
fontSize: 22.0,
),
),
),
),
),
);
}
get firstChooseLanguage {
return Expanded(
child: Material(
color: Colors.white,
child: InkWell(
onTap: () {},
child: Center(
child: Text(
this._firstLanguage,
style: TextStyle(
color: Colors.blue[600],
fontSize: 22.0,
),
),
),
),
),
);
}
Text secondText(Word word) {
return Text(
"Türkçe: ${word.wordTr ?? ""}",
style: TextStyle(
fontWeight: FontWeight.w400,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
);
}
get favoriIconButton {
return IconButton(
alignment: Alignment.topRight,
onPressed: controller.onClickIconButtonFavori,
icon: Icon(
Icons.forward,
color: Colors.blueAccent,
size: 28.0,
),
);
}
FloatingActionButton get _floattingActionButton {
return FloatingActionButton(
onPressed: () {
Get.to(WordListPage());
},
child: Icon(
Icons.app_registration,
size: 30,
),
);
}
Drawer get _drawer {
return Drawer(
child: ListView(
// Important: Remove any padding from the ListView.
padding: EdgeInsets.zero,
children: <Widget>[
userAccountsDrawerHeader,
drawerFavorilerim,
drawersettings,
drawerContacts,
],
),
);
}
ListTile get drawerContacts {
return ListTile(
leading: Icon(Icons.contacts),
title: Text("Contact Us"),
onTap: () {
Get.back();
},
);
}
ListTile get drawersettings {
return ListTile(
leading: Icon(Icons.settings),
title: Text("Settings"),
onTap: () {
Get.back();
},
);
}
ListTile get drawerFavorilerim {
return ListTile(
leading: Icon(
Icons.star,
color: Colors.yellow,
),
title: Text("Favorilerim"),
onTap: () {
Get.to(FavoriListPage());
},
);
}
UserAccountsDrawerHeader get userAccountsDrawerHeader {
return UserAccountsDrawerHeader(
accountName: Text("UserName"),
accountEmail: Text("E-mail"),
currentAccountPicture: CircleAvatar(
backgroundColor: Colors.grey,
child: Text(
"",
style: TextStyle(fontSize: 40.0),
),
),
);
}
}
This error is due to null safety. Try adding ! after every instance of word which you are passing in the function
This question already has answers here:
how to assign future<> to widget in flutter?
(6 answers)
Closed 1 year ago.
I'm building a list of buttons, using Firebase to name each one, but my code presents this error when referencing "_getButtonBar" to the Widget: "The argument type 'Future<List>' can't be assigned to the parameter type 'List'". Should the widget be Future too? Does anyone know what's missing?
class ThemesList extends StatelessWidget {
Future<List<FlatButton>> _getButtonBar(context) async {
List<FlatButton> _list1 = [];
tot = await callReadTotal(); //Receives length to make the loop.
getListCauses(); //Calls Firebase to use arrCauses = List () for child: Text
for (int i = 1; i <= tot; i++) {
_list1.add(
FlatButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0),
side: BorderSide(color: Color.fromRGBO(150, 1, 1, 1)),
),
splashColor: Color.fromRGBO(150, 1, 1, 1),
onPressed: () => {
setChoice(i),
Navigator.push(
context,
MaterialPageRoute(builder: (context) => CausesList()),
),
},
child: Text(
arrCauses[i],
style: TextStyle(
color: Color.fromRGBO(150, 1, 1, 1),
fontSize: 20,
fontFamily: 'Balsamiq_Sans',
),
),
),
);
}
return _list1;
}
#override
Widget build(BuildContext context) {
return Platform.isIOS
? CupertinoPageScaffold(child: null)
: Scaffold(
appBar: AppBar(
title: Text(
'ICare',
style: TextStyle(
color: Color.fromRGBO(150, 1, 1, 1),
fontSize: 40,
fontFamily: 'Balsamiq_Sans',
fontWeight: FontWeight.w500,
),
),
flexibleSpace: Image(
image: AssetImage('assets/images/solidariedade.png'),
color: Color.fromRGBO(255, 200, 200, 0.45),
colorBlendMode: BlendMode.modulate,
fit: BoxFit.cover,
),
),
body: Stack(
children: <Widget>[
Container(
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: ButtonBar(
children: _getButtonBar(
context), //<-- Here it points out the error.
alignment: MainAxisAlignment.center,
),
),
),
],
),
);
}
}
Your problem can be solve via two options.
By using StatefulWidget
import 'package:flutter/material.dart';
class ThemesList extends StatefulWidget {
#override
_ThemesListState createState() => _ThemesListState();
}
class _ThemesListState extends State<ThemesList> {
List<FlatButton> _buttonBar = [];
#override
void initState() {
_getButtonBar();
super.initState();
}
_getButtonBar() async {
List<FlatButton> _list1 = [];
tot = await callReadTotal(); //Receives length to make the loop.
getListCauses(); //Calls Firebase to use arrCauses = List () for child: Text
for (int i = 1; i <= tot; i++) {
_list1.add(
FlatButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0),
side: BorderSide(color: Color.fromRGBO(150, 1, 1, 1)),
),
splashColor: Color.fromRGBO(150, 1, 1, 1),
onPressed: () => {
setChoice(i),
Navigator.push(
context,
MaterialPageRoute(builder: (context) => CausesList()),
),
},
child: Text(
arrCauses[i],
style: TextStyle(
color: Color.fromRGBO(150, 1, 1, 1),
fontSize: 20,
fontFamily: 'Balsamiq_Sans',
),
),
),
);
}
_buttonBar = _list1;
setState(() {});
}
#override
Widget build(BuildContext context) {
return Platform.isIOS
? CupertinoPageScaffold(child: null)
: Scaffold(
appBar: AppBar(
title: Text(
'ICare',
style: TextStyle(
color: Color.fromRGBO(150, 1, 1, 1),
fontSize: 40,
fontFamily: 'Balsamiq_Sans',
fontWeight: FontWeight.w500,
),
),
flexibleSpace: Image(
image: AssetImage('assets/images/solidariedade.png'),
color: Color.fromRGBO(255, 200, 200, 0.45),
colorBlendMode: BlendMode.modulate,
fit: BoxFit.cover,
),
),
body: Stack(
children: <Widget>[
Container(
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: ButtonBar(
children: _buttonBar,
alignment: MainAxisAlignment.center,
),
),
),
],
),
);
}
}
By using FutureBuilder
import 'package:flutter/material.dart';
class ThemesList extends StatelessWidget {
Future<List<FlatButton>> _getButtonBar(context) async {
List<FlatButton> _list1 = [];
tot = await callReadTotal(); //Receives length to make the loop.
getListCauses(); //Calls Firebase to use arrCauses = List () for child: Text
for (int i = 1; i <= tot; i++) {
_list1.add(
FlatButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0),
side: BorderSide(color: Color.fromRGBO(150, 1, 1, 1)),
),
splashColor: Color.fromRGBO(150, 1, 1, 1),
onPressed: () => {
setChoice(i),
Navigator.push(
context,
MaterialPageRoute(builder: (context) => CausesList()),
),
},
child: Text(
arrCauses[i],
style: TextStyle(
color: Color.fromRGBO(150, 1, 1, 1),
fontSize: 20,
fontFamily: 'Balsamiq_Sans',
),
),
),
);
}
return _list1;
}
#override
Widget build(BuildContext context) {
return Platform.isIOS
? CupertinoPageScaffold(child: null)
: Scaffold(
appBar: AppBar(
title: Text(
'ICare',
style: TextStyle(
color: Color.fromRGBO(150, 1, 1, 1),
fontSize: 40,
fontFamily: 'Balsamiq_Sans',
fontWeight: FontWeight.w500,
),
),
flexibleSpace: Image(
image: AssetImage('assets/images/solidariedade.png'),
color: Color.fromRGBO(255, 200, 200, 0.45),
colorBlendMode: BlendMode.modulate,
fit: BoxFit.cover,
),
),
body: Stack(
children: <Widget>[
Container(
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: FutureBuilder<List<FlatButton>>(
future: _getButtonBar(context),
builder: (context,
AsyncSnapshot<List<FlatButton>> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return Text('Loading....');
break;
default:
if (snapshot.hasError)
return Text('Error: ${snapshot.error}');
else
return ButtonBar(
children: snapshot.data,
alignment: MainAxisAlignment.center,
);
}
}),
),
),
],
),
);
}
}
I was working on merging few images and display it as one.
I have two dart files one is for adding images and other is for displaying the merged result.
first file code is,
class SingleImageUpload extends StatefulWidget {
#override
_SingleImageUploadState createState() {
return _SingleImageUploadState();
}
}
class _SingleImageUploadState extends State<SingleImageUpload> {
List<Object> images = List<Object>();
File _selectedFile;
bool _inProcess = false;
Map data = {};
Readerservice _readerservice;
#override
void initState() {
// TODO: implement initState
super.initState();
setState(() {
images.add("Add Image");
images.add("Add Image");
images.add("Add Image");
images.add("Add Image");
});
}
#override
Widget build(BuildContext context) {
return new MaterialApp(
debugShowCheckedModeBanner: false,
home: new Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
leading: Padding(
padding: EdgeInsets.only(left: 12),
child: IconButton(
icon: Icon(Icons.arrow_back_ios,
color: Colors.black,
size: 30,),
onPressed: () {
Navigator.pushNamed(context, '/');
},
),
),
title: Row(
mainAxisAlignment: MainAxisAlignment.center,
children:<Widget>[
Text('Basic AppBar'),
]
),
actions: <Widget>[
IconButton(
icon: Icon(Icons.more_vert,
color: Colors.black,
size: 30,),
onPressed: () {
print('Click start');
},
),
],
),
body:
Column(
children: <Widget>[
SizedBox(height: 10),
Row(children: <Widget>[
Text('Image',
style: TextStyle(
color: Colors.black,
fontSize: 33,
fontWeight: FontWeight.bold,
)),
Text('Merger',
style: TextStyle(
color: Colors.orange,
fontSize: 33,
fontWeight: FontWeight.bold,
)),
]),
SizedBox(height: 40),
Text(' merge it here'),
SizedBox(height: 10),
Expanded(
child: buildGridView(),
),
RaisedButton(
textColor: Colors.white,
color: Colors.orange,
child: Text("Finish",
style: TextStyle(fontSize: 15),),
onPressed: () {
pasimage();
},
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(8.0),
),
),
],
),
),
);
}
Widget buildGridView() {
return GridView.count(
shrinkWrap: true,
crossAxisCount: 3,
childAspectRatio: 1,
children: List.generate(images.length, (index) {
if (images[index] is ImageUploadModel) {
ImageUploadModel uploadModel = images[index];
return Card(
clipBehavior: Clip.antiAlias,
child: Stack(
children: <Widget>[
Image.file(
uploadModel.imageFile,
width: 300,
height: 300,
),
Positioned(
right: 5,
top: 5,
child: InkWell(
child: Icon(
Icons.remove_circle,
size: 20,
color: Colors.red,
),
onTap: () {
setState(() {
images.replaceRange(index, index + 1, ['Add Image']);
});
},
),
),
],
),
);
} else {
return Card(
child: IconButton(
icon: Icon(Icons.add),
onPressed: () {
//popup
showDialog(
context: context,
builder: (context) {
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)),
elevation: 16,
child: Container(
height: 180.0,
width: 330.0,
child: ListView(
children: <Widget>[
SizedBox(height: 20),
//Center(
Padding(
padding: const EdgeInsets.only(left: 15.0),
child: Text(
"Add a Receipt",
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 24,
color: Colors.black,
fontWeight: FontWeight.bold),
),
),
// ),
SizedBox(height: 20),
FlatButton(
child: Text(
'Take a photo..',
textAlign: TextAlign.left,
style: TextStyle(fontSize: 20),
),
onPressed: () {
_onAddImageClick(index,ImageSource.camera);
Navigator.of(context).pop();
// picker.getImage(ImageSource.camera);
},
textColor: Colors.black,
),
FlatButton(
child: Text(
'Choose from Library..',
style: TextStyle(fontSize: 20),
textAlign: TextAlign.left,
),
onPressed: () {
_onAddImageClick(index,ImageSource.gallery);
Navigator.of(context).pop();
},
textColor: Colors.black,
),
],
),
),
);
},
);
//pop ends
},
),
);
}
}),
);
}
Future _onAddImageClick(int index, ImageSource source ) async {
setState(() {
_inProcess = true;
});
File image = await ImagePicker.pickImage(source: source);
if(image != null){
File cropped = await ImageCropper.cropImage(
sourcePath: image.path,
maxWidth: 1080,
maxHeight: 1080,
compressFormat: ImageCompressFormat.jpg,
androidUiSettings: AndroidUiSettings(
toolbarColor: Colors.black,
toolbarWidgetColor: Colors.white,
//toolbarTitle: "RPS Cropper",
statusBarColor: Colors.deepOrange.shade900,
backgroundColor: Colors.black,
initAspectRatio: CropAspectRatioPreset.original,
lockAspectRatio: false
),
iosUiSettings: IOSUiSettings(
minimumAspectRatio: 1.0,
)
);
this.setState((){
_selectedFile = cropped ;
_inProcess = false;
});
} else {
this.setState((){
_inProcess = false;
});
}
getFileImage(index);
}
void getFileImage(int index) async {
// var dir = await path_provider.getTemporaryDirectory();
setState(() {
ImageUploadModel imageUpload = new ImageUploadModel();
imageUpload.isUploaded = false;
imageUpload.uploading = false;
imageUpload.imageFile = _selectedFile;
imageUpload.imageUrl = '';
images.replaceRange(index, index + 1, [imageUpload]);
});
}
void pasimage(){
Navigator.pushReplacementNamed(context, '/crop',arguments: {
'imageList':ImagesMerge(
images,///required,images list
direction: Axis.vertical,///direction
backgroundColor: Colors.black26,///background color
fit: false,///scale image to fit others
),
});
}
}
class ImageUploadModel {
bool isUploaded;
bool uploading;
File imageFile;
String imageUrl;
ImageUploadModel({
this.isUploaded,
this.uploading,
this.imageFile,
this.imageUrl,
});
}
when I tap the finish button after adding the images it shows an error
The following _TypeError was thrown while handling a gesture:
type 'List' is not a subtype of type 'List'
The page just on captures the data sent from the code above and display the image.
please if anyone know why is the error and help me .
Change the images to List<Object> images = [].
I am currently struggling to implement a "list" with two QR-Codes.
I want to change the shown QR code by pressing the arrows left and right to it.
"list" because currently I don't use a list view.
Currently it looks like this: Current App
The QR codes are within a ModalBottomSheet.
Here is my code so far:
void _onButtonPressed() {
bool inAppQr = true;
String _output = "QR 1";
showModalBottomSheet(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
context: context,
builder: (context) {
return Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
_output,
style:
TextStyle(fontWeight: FontWeight.bold, fontSize: 15.0),
),
SizedBox(
height: 30,
),
SizedBox(
height: 5,
width: 150,
child: LinearProgressIndicator(
backgroundColor: Colors.white,
valueColor: AlwaysStoppedAnimation<Color>(
Colors.blueGrey,
),
),
),
SizedBox(
height: 30,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
IconButton(
icon: Icon(Icons.arrow_back_ios),
onPressed: () {
setState(() {
inAppQr = false;
_output = "QR 1";
});
}),
inAppQr == true
? PrettyQr(
typeNumber: 3,
size: 150,
data: 'Test',
errorCorrectLevel: QrErrorCorrectLevel.M,
roundEdges: true)
: PrettyQr(
typeNumber: 3,
size: 150,
data: 'Test 2',
errorCorrectLevel: QrErrorCorrectLevel.M,
roundEdges: true),
IconButton(
icon: Icon(Icons.arrow_forward_ios),
onPressed: () {
setState(() {
_output = "QR 2";
inAppQr = true;
});
}),
],
),
]),
);
});
}
Thanks for your help!
Solution found thanks to Zeeshan Hussain!
I added a StatefulBuilder with the StateSetter newState
This code worked for me:
void _onButtonPressed() {
bool inAppQr = true;
String _output = "QR 1";
showModalBottomSheet(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
context: context,
builder: (context) {
return StatefulBuilder(
builder: (BuildContext context, StateSetter newState) {
return Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
_output,
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 15.0),
),
SizedBox(
height: 30,
),
SizedBox(
height: 5,
width: 150,
child: LinearProgressIndicator(
backgroundColor: Colors.white,
valueColor: AlwaysStoppedAnimation<Color>(
Colors.blueGrey,
),
),
),
SizedBox(
height: 30,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
IconButton(
icon: Icon(Icons.arrow_back_ios),
onPressed: () {
newState(() {
inAppQr = true;
_output = "QR 1";
});
}),
inAppQr == true
? PrettyQr(
typeNumber: 3,
size: 150,
data: 'Test',
errorCorrectLevel: QrErrorCorrectLevel.M,
roundEdges: true)
: PrettyQr(
typeNumber: 3,
size: 150,
data: 'Test 2',
errorCorrectLevel: QrErrorCorrectLevel.M,
roundEdges: true),
IconButton(
icon: Icon(Icons.arrow_forward_ios),
onPressed: () {
newState(() {
_output = "QR 2";
inAppQr = false;
});
}),
],
),
]),
);
},
);
});
I have previously asked a question regarding lists in Flutter. I got good help but new problems arose within the same list. Since this new probelm is of other character then the initial question I made this new question.
I have a list (the code below is simplified from my working-code to make my problem clearer) of blue colored containers.
When the user types in 5 and press the 'submit'-button the color of the first container should change to green (if not 5 the button should turn red).
The second time the user press the 'submit'-button the second container should change color. And so on...
The problem I'm facing is that I can't get my increment to the list to work.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'listing 4',
theme: ThemeData(primarySwatch: Colors.blue),
home: FirstScreen(),
);
}
}
class FirstScreen extends StatefulWidget {
#override
_FirstScreenState createState() => _FirstScreenState();
}
class _FirstScreenState extends State<FirstScreen> {
int sum = 5;
String userAnswer;
String correction = "";
var _controller = new TextEditingController();
int _counter = 1;
List<Color> colors = [Colors.blue, Colors.blue, Colors.blue];
submitPressed(int index) {
if (userAnswer == sum.toString()) {
setState(() {
correction = sum.toString();
colors[index] = Colors.green;
});
} else {
setState(() {
correction = sum.toString();
colors[index] = Colors.red;
});
}
}
Widget myTextField() {
return Container(
width: 50.0,
child: TextField(
controller: _controller,
textAlign: TextAlign.center,
autofocus: true,
keyboardType: TextInputType.number,
onChanged: (val) {
userAnswer = val;
},
),
);
}
Widget myListBuilder() {
return Container(
height: 50.0,
width: 300.0,
child: Padding(
padding: const EdgeInsets.all(10.0),
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 3,
itemBuilder: buildContainer,
),
),
);
}
Widget buildContainer(BuildContext context, int index) {
return Container(
child: Padding(
padding: const EdgeInsets.only(top: 10.0),
child: Container(
height: 20.0,
width: 15.0,
decoration: BoxDecoration(
color: colors[index], //this is the important line
borderRadius: BorderRadius.all(Radius.circular(8.0))),
),
));
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text('Listing 4'),
),
body: Container(
child: Center(
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 10.0),
child: Text('Correct answer is 5',
style: TextStyle(fontSize: 20.0)),
),
myTextField(),
RaisedButton(
child: Text('Submit'),
onPressed: () {
setState(() {
submitPressed(0); //This will naturally only give index 0
});
},
),
myListBuilder(),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
buildContainer(context, 0),
buildContainer(context, 1),
buildContainer(context, 2)
],
),
RaisedButton(
child: Text('Next'),
onPressed: () {
_counter++;
_controller.clear();
myTextField();
},
),
Text('This should be container no: $_counter'),
],
),
),
),
);
}
}
I can't figure out why you have this
submitPressed(0);
This code works:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'listing 4',
theme: ThemeData(primarySwatch: Colors.blue),
home: FirstScreen(),
);
}
}
class FirstScreen extends StatefulWidget {
#override
_FirstScreenState createState() => _FirstScreenState();
}
class _FirstScreenState extends State<FirstScreen> {
int sum = 5;
String userAnswer;
String correction = "";
var _controller = new TextEditingController();
int _counter = 0;
List<Color> colors = [Colors.blue, Colors.blue, Colors.blue];
submitPressed(int index) {
if (userAnswer == sum.toString()) {
setState(() {
correction = sum.toString();
colors[index] = Colors.green;
});
} else {
setState(() {
correction = sum.toString();
colors[index] = Colors.red;
});
}
}
Widget myTextField() {
return Container(
width: 50.0,
child: TextField(
controller: _controller,
textAlign: TextAlign.center,
autofocus: true,
keyboardType: TextInputType.number,
onChanged: (val) {
userAnswer = val;
},
),
);
}
Widget myListBuilder() {
return Container(
height: 50.0,
width: 300.0,
child: Padding(
padding: const EdgeInsets.all(10.0),
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 3,
itemBuilder: buildContainer,
),
),
);
}
Widget buildContainer(BuildContext context, int index) {
return Container(
child: Padding(
padding: const EdgeInsets.only(top: 10.0),
child: Container(
height: 20.0,
width: 15.0,
decoration: BoxDecoration(
color: colors[index], //this is the important line
borderRadius: BorderRadius.all(Radius.circular(8.0))),
),
));
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text('Listing 4'),
),
body: Container(
child: Center(
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 10.0),
child: Text('Correct answer is 5',
style: TextStyle(fontSize: 20.0)),
),
myTextField(),
RaisedButton(
child: Text('Submit'),
onPressed: () {
setState(() {
submitPressed(_counter);
});
},
),
myListBuilder(),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
buildContainer(context, 0),
buildContainer(context, 1),
buildContainer(context, 2)
],
),
RaisedButton(
child: Text('Next'),
onPressed: () {
setState(() {
_counter++;
});
_controller.clear();
myTextField();
},
),
Text('This should be container no: ${_counter +1}'),
],
),
),
),
);
}
}
I changed the _counter to act like an index and use it as the parameter of the method submitPressed.
I also put the increment in a setState, or you saw the new number only after hitting the Submit button.