Currently, I am working on the update profile portion of the app but there is seems to be an issue. The issue is when we want to go to the page we want to see the text field loaded up with the uses of previous data or old data. To do that we use a future builder to get the data and then set it to the field. But when we use the keyboard on mobile devices to tap and edit the text fields what happens is the future builder gets rebuilt again just because a build is invoked due to this changing of the size of the screen, the keyboard coming up and down. In our to fix his what I had to do was create a temporary future variable and it only updates if it's null. On top of that, the text field only updates if the count is equal to a certain value IE, in this case, one but it's not working. We want to place text in the text field every time we go to the page AKA refresh or click on the submit button. This is where I'm kind of having trouble. I have tried using states and I get the same result, maybe I'm setting it up wrong.
Goal: Load data, set text fields with data that I just got, edit them as I need them to (data stays as is with the keyboard going up or down). Then update that data via the update button.
old:
class Test extends StatelessWidget {
Future<void> getFuture() async {
_profile = await HTTP.getProfile();
}
Widget build(BuildContext context) {
return FutureBuilder(
future: getFuture(); // generate every time
builder: () {
return nameFeild();
}
)
}
Widget nameFeild(){
_changeNameController.text = _profile.name;
return TextField(controller: _nameController);
}
}
new:
class Test extends StatelessWidget {
Future testFuture;
static int count = 0;
Future<void> getFuture() async {
_profile = await HTTP.getProfile();
}
Widget build(BuildContext context) {
testFuture ??= getFuture();
count++;
return FutureBuilder(
future: testFuture; // generate every time
builder: () {
return nameFeild();
}
)
}
Widget nameFeild(){
if(count == 1){
_changeNameController.text = _profile.name;
}
return TextField(controller: _nameController);
}
}
Actual code
// imports
class UserSettingPage extends StatelessWidget {
BuildContext context;
GetSizes _sizes;
double _w;
double _h;
NavbarWidget _navBar = NavbarWidget();
FooterWidget _footer = FooterWidget.autoPosition();
ImageProvider _userPicture =
AssetImage('assets/images/team/zain.png'); //Defaultpic.png');
Cookies _cookies = Cookies();
final _oldPasswordControllerOne = TextEditingController();
final _resetPasswordControllerOne = TextEditingController();
final _resetPasswordControllerTwo = TextEditingController();
final _changeNameController = TextEditingController();
final _changeBioController = TextEditingController();
final _changeNumberController = TextEditingController();
final _changeFacebookController = TextEditingController();
final _changeTwitterController = TextEditingController();
final _changeInstagramController = TextEditingController();
CheckBoxValueNotifier email = new CheckBoxValueNotifier(false);
CheckBoxValueNotifier phone = new CheckBoxValueNotifier(false);
bool _isDesktop;
Authentication _authentication = Authentication();
Encryption _encryption = Encryption();
DialogBox _dialog = DialogBox();
passwordValidNotifier passwordNotifier = new passwordValidNotifier();
ProfileModel _user;
Uint8List _base64;
bool phoneCheckedValue = false;
bool emailCheckedValue = false;
String userID;
FilePickerWidget imagePicker = FilePickerWidget();
Future _getUser;
static int count = 0;
Future<String> retrieveUser() async {
userID = await Cookies.getCookieValue("userID");
await DioCalls.getProfile(context, userID).then((value) => _user = value);
}
@override
Widget build(BuildContext context) {
this.context = context;
_sizes = GetSizes(context);
_w = _sizes.getPageWidth();
_h = _sizes.getPageHeight();
_isDesktop = _sizes.isDesktop();
print('Update Data: ' + (_getUser == null).toString() + ' count: ' + count.toString());
_getUser ??= retrieveUser();
count++;
return LayoutBuilder(builder: (context, constraints) {
if (_sizes.isDesktop()) {
return _bigDisplay();
} else {
return _smallDisplay();
}
});
}
Widget _bigDisplay() {
// code
}
Widget _smallDisplay() {
return FutureBuilder(
future: _getUser,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: Text(''));
} else {
if (snapshot.hasError) {
return Center(child: Text('Errors: ${snapshot.error}'));
} else {
return Scaffold(
backgroundColor: Colors.white,
body: Column(
children: [
_navBar,
Expanded(
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [userPictureAndBorder()],
),
userInfo(),
line(),
changeNameTile(),
line(),
changeBioTile(),
line(),
changeSocialMediaTile(),
line(),
changeNotificationTile(),
line(),
changePasswordTile(),
line(),
Container(
margin: EdgeInsets.fromLTRB(0, 10, 0, 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [logoutButton(), updateButton(context)],
),
)
],
),
),
)
],
),
);
}
}
},
);
}
// OTHER WIDGETS CODE WERE REMOVED, I dont think you need them
Widget userInfo() {
return Container(
margin: EdgeInsets.fromLTRB(0, 5, 0, 10),
alignment: Alignment.center,
child: Column(
children: [
SelectableText(
_user.userID,
style: TextStyle(
fontWeight: FontWeight.w800,
fontSize: 14,
color: Colors.black,
// height: 21,
),
),
SelectableText(
_user.name,
style: TextStyle(
fontWeight: FontWeight.w400,
fontSize: 14,
color: Colors.black,
// height: 21,
),
),
SelectableText(
'732-318-5555 (change)',
style: TextStyle(
fontWeight: FontWeight.w400,
fontSize: 14,
color: Colors.black,
// height: 21,
),
),
],
),
);
}
Widget logoutButton() {
return ElevatedButton.icon(
onPressed: () {
print('Logging out');
},
icon: Icon(Icons.logout),
label: Text("Logout"),
style: ElevatedButton.styleFrom(
primary: Colors.black, // background
onPrimary: Colors.white, // foreground
),
);
}
Widget updateButton(BuildContext context) {
return ElevatedButton.icon(
onPressed: () async {
_user.name = _changeNameController.text;
_user.bio = _changeBioController.text;
_user.socialMedia.Facebook = _changeFacebookController.text;
_user.socialMedia.Instagram = _changeInstagramController.text;
_user.socialMedia.Twitter = _changeTwitterController.text;
DioCalls.updateProfile(context, _user, imagePicker.selectedFile,
await Cookies.getCookieValue("jwt"));
Navigator.pop(context); // pop current page
Navigator.pushNamed(context, "/test1"); // push it back in
_oldPasswordControllerOne.clear();
_changeBioController.clear();
count = 0;
_getUser = null;
},
icon: Icon(Icons.update),
label: Text("Update"),
style: ElevatedButton.styleFrom(
primary: Colors.black, // background
onPrimary: Colors.white, // foreground
),
);
}
Widget nameTextField() {
return SelectableText(
"Edit Name",
textAlign: TextAlign.start,
style: TextStyle(
fontSize: 16,
fontStyle: FontStyle.normal,
fontFamily: 'Poppins-Black',
fontWeight: FontWeight.w500,
),
);
}
Widget bioTextField() {
return SelectableText(
"Edit Bio (Max: 100)",
textAlign: TextAlign.start,
style: TextStyle(
fontSize: 16,
fontStyle: FontStyle.normal,
fontFamily: 'Poppins-Black',
fontWeight: FontWeight.w500,
),
);
}
Widget changeNameTile() {
if (count == 1) {
print('updating text');
_changeNameController.text = _user.name;
}
return ExpansionTile(
title: Text(
'Name',
style: TextStyle(
fontSize: (_sizes.isDesktop()) ? 16 : 12,
fontWeight: FontWeight.w500,
color: Colors.black),
textAlign: TextAlign.left,
),
children: [
nameTextField(),
Container(
margin: EdgeInsets.all(20),
child: Theme(
data: ThemeData(
primaryColor: Colors.transparent,
hintColor: Colors.transparent),
child: TextField(
maxLength: 50,
controller: _changeNameController,
decoration: InputDecoration(
counterText: '',
contentPadding: EdgeInsets.all(20.0),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(),
borderRadius: BorderRadius.all(Radius.circular(
10) // <--- border radius here
),
),
errorBorder: OutlineInputBorder(
borderSide: BorderSide(color: Theme.of(context).errorColor),
borderRadius: BorderRadius.all(Radius.circular(
10) // <--- border radius here
),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Theme.of(context).primaryColor),
borderRadius: BorderRadius.all(Radius.circular(
10) // <--- border radius here
),
),
border: OutlineInputBorder(
borderSide: BorderSide(),
borderRadius: BorderRadius.all(Radius.circular(
10) // <--- border radius here
),
),
),
),
),
)
],
);
}
Widget changeBioTile() {
if (count == 1) {
_changeBioController.text = _user.bio;
}
return ExpansionTile(
title: Text(
'Bio',
style: TextStyle(
fontSize: (_sizes.isDesktop()) ? 16 : 12,
fontWeight: FontWeight.w500,
color: Colors.black),
textAlign: TextAlign.left,
),
children: [
bioTextField(),
Container(
margin: EdgeInsets.all(20),
child: Theme(
data: ThemeData(
primaryColor: Colors.transparent,
hintColor: Colors.transparent),
child: TextField(
maxLength: 100,
controller: _changeBioController,
decoration: InputDecoration(
counterText: '',
contentPadding: EdgeInsets.all(20.0),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(),
borderRadius: BorderRadius.all(Radius.circular(
10) // <--- border radius here
),
),
errorBorder: OutlineInputBorder(
borderSide: BorderSide(color: Theme.of(context).errorColor),
borderRadius: BorderRadius.all(Radius.circular(
10) // <--- border radius here
),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Theme.of(context).primaryColor),
borderRadius: BorderRadius.all(Radius.circular(
10) // <--- border radius here
),
),
border: OutlineInputBorder(
borderSide: BorderSide(),
borderRadius: BorderRadius.all(Radius.circular(
10) // <--- border radius here
),
),
),
),
),
)
],
);
}
Widget changeSocialMediaTile() {
if (count == 1) {
_changeFacebookController.text = _user.socialMedia.Facebook;
_changeTwitterController.text = _user.socialMedia.Twitter;
_changeInstagramController.text = _user.socialMedia.Instagram;
}
return ExpansionTile(
title: Text(
'Social Media',
style: TextStyle(
fontSize: (_sizes.isDesktop()) ? 16 : 12,
fontWeight: FontWeight.w500,
color: Colors.black),
textAlign: TextAlign.left,
),
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
MyFlutterApp.facebook,
color: Colors.blue,
size: 30,
),
SelectableText("www.Facebook.com/"),
Container(
margin: EdgeInsets.all(5),
width: 200,
child: Theme(
data: ThemeData(
primaryColor: Colors.transparent,
hintColor: Colors.transparent),
child: TextField(
maxLength: 100,
controller: _changeFacebookController,
decoration: InputDecoration(
counterText: '',
contentPadding: EdgeInsets.all(5.0),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(),
borderRadius: BorderRadius.all(Radius.circular(
10) // <--- border radius here
),
),
errorBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Theme.of(context).errorColor),
borderRadius: BorderRadius.all(Radius.circular(
10) // <--- border radius here
),
),
focusedBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Theme.of(context).primaryColor),
borderRadius: BorderRadius.all(Radius.circular(
10) // <--- border radius here
),
),
border: OutlineInputBorder(
borderSide: BorderSide(),
borderRadius: BorderRadius.all(Radius.circular(
10) // <--- border radius here
),
),
),
),
),
)
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
MyFlutterApp.twitter,
color: Colors.lightBlue,
size: 30,
),
SelectableText("www.Twitter.com/ "),
Container(
margin: EdgeInsets.all(5),
width: 200,
child: Theme(
data: ThemeData(
primaryColor: Colors.transparent,
hintColor: Colors.transparent),
child: TextField(
maxLength: 100,
controller: _changeTwitterController,
decoration: InputDecoration(
counterText: '',
contentPadding: EdgeInsets.all(5.0),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(),
borderRadius: BorderRadius.all(Radius.circular(
10) // <--- border radius here
),
),
errorBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Theme.of(context).errorColor),
borderRadius: BorderRadius.all(Radius.circular(
10) // <--- border radius here
),
),
focusedBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Theme.of(context).primaryColor),
borderRadius: BorderRadius.all(Radius.circular(
10) // <--- border radius here
),
),
border: OutlineInputBorder(
borderSide: BorderSide(),
borderRadius: BorderRadius.all(Radius.circular(
10) // <--- border radius here
),
),
),
),
),
)
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(MyFlutterApp.instagram, color: Colors.black, size: 30.0),
SelectableText("www.Instagram.com/"),
Container(
margin: EdgeInsets.all(5),
width: 200,
child: Theme(
data: ThemeData(
primaryColor: Colors.transparent,
hintColor: Colors.transparent),
child: TextField(
maxLength: 100,
controller: _changeInstagramController,
decoration: InputDecoration(
counterText: '',
contentPadding: EdgeInsets.all(5.0),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(),
borderRadius: BorderRadius.all(Radius.circular(
10) // <--- border radius here
),
),
errorBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Theme.of(context).errorColor),
borderRadius: BorderRadius.all(Radius.circular(
10) // <--- border radius here
),
),
focusedBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Theme.of(context).primaryColor),
borderRadius: BorderRadius.all(Radius.circular(
10) // <--- border radius here
),
),
border: OutlineInputBorder(
borderSide: BorderSide(),
borderRadius: BorderRadius.all(Radius.circular(
10) // <--- border radius here
),
),
),
),
),
)
],
)
],
);
}
Widget changeNotificationTile() {
return ExpansionTile(
title: Text(
'Notifications',
style: TextStyle(
fontSize: (_sizes.isDesktop()) ? 16 : 12,
fontWeight: FontWeight.w500,
color: Colors.black),
textAlign: TextAlign.left,
),
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.phone_iphone),
Container(
margin: EdgeInsets.all(5),
width: 200,
child: Theme(
data: ThemeData(
primaryColor: Colors.transparent,
hintColor: Colors.transparent),
child: TextField(
maxLength: 100,
controller: _changeNumberController,
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.allow(RegExp(r'[0-9]')),
],
decoration: InputDecoration(
counterText: '',
contentPadding: EdgeInsets.all(5.0),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(),
borderRadius: BorderRadius.all(Radius.circular(
10) // <--- border radius here
),
),
errorBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Theme.of(context).errorColor),
borderRadius: BorderRadius.all(Radius.circular(
10) // <--- border radius here
),
),
focusedBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Theme.of(context).primaryColor),
borderRadius: BorderRadius.all(Radius.circular(
10) // <--- border radius here
),
),
border: OutlineInputBorder(
borderSide: BorderSide(),
borderRadius: BorderRadius.all(Radius.circular(
10) // <--- border radius here
),
),
),
),
),
)
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 275,
child: emailTile(
checkBoxValueNotifier: email,
),
)
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 275,
child: phoneTile(
checkBoxValueNotifier: phone,
),
)
],
)
],
);
}
}
class emailTile extends StatefulWidget {
@override
final CheckBoxValueNotifier checkBoxValueNotifier;
const emailTile({Key key, this.checkBoxValueNotifier}) : super(key: key);
_emailTileState createState() => _emailTileState();
}
class _emailTileState extends State<emailTile> {
@override
Widget build(BuildContext context) {
return CheckboxListTile(
value: widget.checkBoxValueNotifier.check.value,
secondary: Icon(
Icons.email_rounded,
color: Colors.black,
size: 30,
),
title: SelectableText("Email Notifications"),
onChanged: (newValue) {
setState(() {
widget.checkBoxValueNotifier.check.value =
!widget.checkBoxValueNotifier.check.value;
});
},
controlAffinity:
ListTileControlAffinity.trailing, // <-- leading Checkbox
);
}
}
class phoneTile extends StatefulWidget {
@override
final CheckBoxValueNotifier checkBoxValueNotifier;
const phoneTile({Key key, this.checkBoxValueNotifier}) : super(key: key);
_phoneTileState createState() => _phoneTileState();
}
class _phoneTileState extends State<phoneTile> {
@override
Widget build(BuildContext context) {
return CheckboxListTile(
value: widget.checkBoxValueNotifier.check.value,
secondary: Icon(
Icons.phone_iphone,
color: Colors.black,
size: 30,
),
title: SelectableText("Phone Notifications"),
onChanged: (newValue) {
setState(() {
widget.checkBoxValueNotifier.check.value =
!widget.checkBoxValueNotifier.check.value;
});
},
controlAffinity:
ListTileControlAffinity.trailing, // <-- leading Checkbox
);
}
}
class CheckBoxValueNotifier {
ValueNotifier check;
CheckBoxValueNotifier(bool init) {
check = ValueNotifier(init);
}
void toggleNotifier() {
check.value = !check.value;
}
}