setState updating inside StatefulBuilder but not updating when using a method outside - flutter

I am having a showMyModalBottomSheet that calls showModalBottomSheet which returns StatefulBuilder that has some widgets. The problem i am having is that if i setState it just works fine but if i setState in a method that i have called it does not work.
Below is my showMyModalBottomSheet method
showMyModalBottomSheet() {
showModalBottomSheet(
context: context,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(25))),
builder: (context) {
return StatefulBuilder(builder: (context, setState) {
return Container(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
child: SingleChildScrollView(
child: Container(
width: double.infinity,
child: Column(children: [
Container(
width: double.infinity,
margin: const EdgeInsets.only(
left: 10, right: 10, top: 20, bottom: 20),
child: Text(
_titleText,
textAlign: TextAlign.center,
style:
TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
),
),
Container(
width: double.infinity,
margin: const EdgeInsets.only(
left: 20, right: 20, top: 10, bottom: 10),
child: TextFormField(
key: _titleFormKey,
decoration: InputDecoration(labelText: "Enter Title"),
controller: _titleController,
validator: (title) {
if (title!.isEmpty) {
return "Please enter title";
} else {
return null;
}
},
),
),
Container(
child: ElevatedButton(
onPressed: () {
if (_titleFormKey.currentState!.validate()) {
// updating title
_titleText = _titleController.text.trim().toString();
}
},
child: Text("Update Title"),
),
)
]),
),)
);
});
});
}
When i am updating my _titleText using below way it just works fine
onPressed: () {
if (_titleFormKey.currentState!.validate()) {
_titleText = _titleController.text.trim().toString();
}
},
But when i am using my method updateTitle like below it does not update
onPressed: () {
if (_titleFormKey.currentState!.validate()) {
updateTitle(_titleController.text.trim().toString());
}
},
And below is my updateTitle method
updateTitle(String title){
setState(() {
_titleText = title;
});
}
Below is my entire code
import 'package:flutter/material.dart';
class MyPage extends StatefulWidget {
const MyPage({Key? key}) : super(key: key);
#override
State<MyPage> createState() => _MyPageState();
}
class _MyPageState extends State<MyPage> {
String _titleText = "Test Title";
final _titleFormKey = GlobalKey<FormFieldState>();
TextEditingController _titleController = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("My Page"),
),
body: Center(
child: ElevatedButton(
onPressed: () {
showMyModalBottomSheet();
},
child: Text("Show Bottom Sheet"),
),
),
);
}
showMyModalBottomSheet() {
showModalBottomSheet(
context: context,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(25))),
builder: (context) {
return StatefulBuilder(builder: (context, setState) {
return Container(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
child: SingleChildScrollView(
child: Container(
width: double.infinity,
child: Column(children: [
Container(
width: double.infinity,
margin: const EdgeInsets.only(
left: 10, right: 10, top: 20, bottom: 20),
child: Text(
_titleText,
textAlign: TextAlign.center,
style:
TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
),
),
Container(
width: double.infinity,
margin: const EdgeInsets.only(
left: 20, right: 20, top: 10, bottom: 10),
child: TextFormField(
key: _titleFormKey,
decoration: InputDecoration(labelText: "Enter Title"),
controller: _titleController,
validator: (title) {
if (title!.isEmpty) {
return "Please enter title";
} else {
return null;
}
},
),
),
Container(
child: ElevatedButton(
onPressed: () {
if (_titleFormKey.currentState!.validate()) {
updateTitle(_titleController.text.trim().toString());
}
},
child: Text("Update Title"),
),
)
]),
),)
);
});
});
}
updateTitle(String title){
setState(() {
_titleText = title;
});
}
}
The problem is that its not updating text whenever i setState using updateTitle method.

updateTitle is using state class(_MyPageState) setState, that's why it is not updating. You can pass setState of StatefulBuilder while StatefulBuilder's setState is out of scope.
updateTitle(
_titleController.text.trim().toString(),
setState);
And
updateTitle(String title, setState) {
setState(() {
_titleText = title;
});
}

Related

Flutter ListView builder not updating with fresh data

I'm running a search filter function which retrieves players from a Floor DB. The functionality works fine and I can see through logs that the new player are returned, however my UI won't update which seems to be from the new list i assign not triggering a re-render.
Can anyone see what's wrong with my code?
import 'package:flutter/material.dart';
import '../database/LocalDatabase.dart';
import '../model/Player.dart';
class Pitch extends StatefulWidget {
const Pitch({super.key});
#override
_Pitch createState() => _Pitch();
}
class _Pitch extends State<Pitch> {
List<Player> playersList = <Player>[];
Offset positionOne = const Offset(100, 100);
Offset positionTwo = const Offset(200, 100);
#override
Widget build(BuildContext context) {
return Container(
constraints: BoxConstraints.expand(),
color: Colors.white,
child: Stack(
alignment: Alignment.center,
children: [
Image.asset("assets/images/pitch.png"),
Positioned(
left: positionOne.dx,
top: positionOne.dy,
child: Draggable(
feedback: playerImage(
"https://cdn.sofifa.net/players/158/023/22_120.png"),
childWhenDragging: Opacity(
opacity: 0,
child: playerImage(
"https://cdn.sofifa.net/players/158/023/22_120.png"),
),
child: playerImage(
"https://cdn.sofifa.net/players/158/023/22_120.png"),
onDragEnd: (details) {
setState(() {
positionOne = details.offset;
});
},
),
),
Positioned(
left: positionTwo.dx,
top: positionTwo.dy,
child: Draggable(
feedback: playerImage(
"https://cdn.sofifa.com/players/notfound_0_120.png"),
childWhenDragging: Opacity(
opacity: 0,
child: playerImage(
"https://cdn.sofifa.com/players/notfound_0_120.png"),
),
child: playerImage(
"https://cdn.sofifa.com/players/notfound_0_120.png"),
onDragEnd: (details) {
setState(() {
positionTwo = details.offset;
});
},
),
)
],
),
);
}
#override
void initState() {
super.initState();
// getPlayers().then((value) {
// debugPrint("playerfromdb: ${value[0].name}");
// });
}
Future<List<Player>> getPlayers() async {
final database =
await $FloorLocalDatabase.databaseBuilder('local_database.db').build();
final playerDao = database.playerDao;
final players = playerDao.getAllPlayers();
return players;
}
Widget playerImage(String imageUrl) {
return GestureDetector(
onTap: () => showDialog<void>(
context: context,
builder: (BuildContext context) => Dialog(
backgroundColor: Colors.white,
child: SizedBox(
height: 300,
width: 300,
child: Column(
children: [
const SizedBox(height: 24),
Container(
margin: const EdgeInsets.only(left: 16),
height: 48,
child: TextField(
decoration: const InputDecoration.collapsed(
hintText: 'Enter player name',
focusColor: Colors.transparent),
onChanged: (value) {
searchPlayers(value);
},
)),
const SizedBox(height: 24),
SizedBox(
height: 200,
child: ListView.builder(
itemCount: playersList.length,
itemBuilder: (context, index) {
return playerItem(playersList.elementAt(index));
}),
),
],
)))),
child: SizedBox(
width: 48,
height: 48,
child: Image.network(imageUrl),
));
}
Widget playerItem(Player? player) {
return Container(
height: 48,
margin: const EdgeInsets.all(8),
padding: const EdgeInsets.only(left: 8, right: 8),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: const [BoxShadow(blurRadius: 8)]),
child: Row(
children: [
SizedBox(
height: 36,
width: 36,
child: Image.network(player?.playerImageUrl ?? "")),
const SizedBox(width: 8),
Text(player?.name ?? "")
],
),
);
}
Future<void> searchPlayers(String query) async {
final database = await $FloorLocalDatabase
.databaseBuilder('local_database.db')
.build();
final playerDao = database.playerDao;
// await List<Player> filteredPlayers =
playerDao.searchPlayers(query).then((value) {
setState(() => playersList = value);
debugPrint(value[0].name);
});
}
}
Because your put ListView.builder in Dialog it will create a new stack and a new stack can't rerender from another stack
You can change your code with create a new stateful widget for dialogs
import 'package:flutter/material.dart';
import '../database/LocalDatabase.dart';
import '../model/Player.dart';
class Pitch extends StatefulWidget {
const Pitch({super.key});
#override
_Pitch createState() => _Pitch();
}
class _Pitch extends State<Pitch> {
Offset positionOne = const Offset(100, 100);
Offset positionTwo = const Offset(200, 100);
#override
Widget build(BuildContext context) {
return Container(
constraints: BoxConstraints.expand(),
color: Colors.white,
child: Stack(
alignment: Alignment.center,
children: [
Image.asset("assets/images/pitch.png"),
Positioned(
left: positionOne.dx,
top: positionOne.dy,
child: Draggable(
feedback: playerImage(
"https://cdn.sofifa.net/players/158/023/22_120.png"),
childWhenDragging: Opacity(
opacity: 0,
child: playerImage(
"https://cdn.sofifa.net/players/158/023/22_120.png"),
),
child: playerImage(
"https://cdn.sofifa.net/players/158/023/22_120.png"),
onDragEnd: (details) {
setState(() {
positionOne = details.offset;
});
},
),
),
Positioned(
left: positionTwo.dx,
top: positionTwo.dy,
child: Draggable(
feedback: playerImage(
"https://cdn.sofifa.com/players/notfound_0_120.png"),
childWhenDragging: Opacity(
opacity: 0,
child: playerImage(
"https://cdn.sofifa.com/players/notfound_0_120.png"),
),
child: playerImage(
"https://cdn.sofifa.com/players/notfound_0_120.png"),
onDragEnd: (details) {
setState(() {
positionTwo = details.offset;
});
},
),
)
],
),
);
}
Widget playerImage(String imageUrl) {
return GestureDetector(
onTap: () => showDialog<void>(
context: context,
builder: (BuildContext context) => Dialog(
backgroundColor: Colors.white,
child: const PlayersDialog(),
),
),
child: SizedBox(
width: 48,
height: 48,
child: Image.network(imageUrl),
),
);
}
}
class PlayersDialog extends StatefulWidget {
const PlayersDialog({super.key});
#override
_PlayersDialog createState() => _PlayersDialog();
}
class _PlayersDialog extends State<PlayersDialog> {
List<Player> playersList = <Player>[];
Future<void> searchPlayers(String query) async {
final database =
await $FloorLocalDatabase.databaseBuilder('local_database.db').build();
final playerDao = database.playerDao;
// await List<Player> filteredPlayers =
playerDao.searchPlayers(query).then((value) {
setState(() => playersList = value);
debugPrint(value[0].name);
});
}
#override
Widget build(BuildContext context) {
return SizedBox(
height: 300,
width: 300,
child: Column(
children: [
const SizedBox(height: 24),
Container(
margin: const EdgeInsets.only(left: 16),
height: 48,
child: TextField(
decoration: const InputDecoration.collapsed(
hintText: 'Enter player name',
focusColor: Colors.transparent),
onChanged: (value) {
searchPlayers(value);
},
)),
const SizedBox(height: 24),
SizedBox(
height: 200,
child: ListView.builder(
itemCount: playersList.length,
itemBuilder: (context, index) {
return playerItem(playersList.elementAt(index));
},
),
),
],
),
);
}
Widget playerItem(Player? player) {
return Container(
height: 48,
margin: const EdgeInsets.all(8),
padding: const EdgeInsets.only(left: 8, right: 8),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: const [BoxShadow(blurRadius: 8)]),
child: Row(
children: [
SizedBox(
height: 36,
width: 36,
child: Image.network(player?.playerImageUrl ?? "")),
const SizedBox(width: 8),
Text(player?.name ?? "")
],
),
);
}
#override
void initState() {
super.initState();
// getPlayers().then((value) {
// debugPrint("playerfromdb: ${value[0].name}");
// });
}
Future<List<Player>> getPlayers() async {
final database =
await $FloorLocalDatabase.databaseBuilder('local_database.db').build();
final playerDao = database.playerDao;
final players = playerDao.getAllPlayers();
return players;
}
}

Screen does not update even though build function is running flutter

So I have created a chat app which draws from a pusher client. Whenever there is a new message, the build function does rebuild, and I believe the widget list does change, but there is no update on the screen. How do I fix this ?
Widget build(BuildContext context) {
// print(messageWidgetList.length);
return Scaffold(
backgroundColor: AppColors.lightGrey,
appBar: AppBar(
backgroundColor: Colors.transparent,
title: Text(
messageTo,
style: TextStyle(
color: AppColors.white,
fontSize: 22,
),
),
),
body: Stack(
children: [
Padding(
padding:
const EdgeInsets.only(top: 12, left: 12, right: 12, bottom: 70),
child: ValueListenableBuilder<List<Widget>>(
valueListenable: messageWidgetList,
builder: (context, value, widget) {
print("Updated");
print(value.length);
// print(widget);
return ListView.builder(
// controller: scrollController,
physics: AlwaysScrollableScrollPhysics(),
reverse: true,
addAutomaticKeepAlives: true,
itemCount: value.length,
itemBuilder: (ctx, index) {
// print(index);
return value[index];
},
);
},
),
),
Align(
alignment: Alignment.bottomCenter,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
if (xFilesImages.isNotEmpty)
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: xFilesImages.map<Widget>((element) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: SizedBox(
height: 100,
width: 80,
child: Image.file(
File(element.path),
frameBuilder:
(ctx, child, frame, wasSynchronouslyLoaded) {
return SizedBox(
width: MediaQuery.of(ctx).size.width,
height: MediaQuery.of(ctx).size.height,
child: Stack(
children: [
Align(
alignment: Alignment.topRight,
child: Container(
height: 25,
width: 25,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: AppColors.lightestGrey,
),
child: FittedBox(
child: GestureDetector(
onTap: () {
xFilesImages.remove(element);
setState(() {});
},
child:
const Icon(Icons.cancel)),
),
),
),
child
],
),
);
},
),
),
);
}).toList(),
),
),
const SizedBox(height: 5),
Container(
height: 60,
width: MediaQuery.of(context).size.width,
child: Padding(
padding:
const EdgeInsets.only(left: 10, bottom: 10, right: 10),
child: Container(
// height: 30,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: AppColors.darkGrey,
),
child: TextFormField(
// expands: true,
style: TextStyle(color: AppColors.white),
focusNode: messageFocusNode,
controller: messageController,
decoration: InputDecoration(
contentPadding: const EdgeInsets.only(
right: 8, left: 8, top: 14),
prefixIcon: InkWell(
onTap: () async {
if (!(await Permission.camera.isGranted)) {
await Permission.camera.request();
await Permission.photos.request();
}
ImagePicker _picker = ImagePicker();
xFilesImages =
await _picker.pickMultiImage() ?? [];
print("Got xFiles");
print(xFilesImages.length);
for (XFile xFile in xFilesImages) {
print(xFile.name);
print(xFile.path);
}
setState(() {});
},
child: Icon(
Icons.attachment,
size: 34,
color: AppColors.lightestGrey,
),
),
suffixIcon: GestureDetector(
onTap: () async {
//TODO: When you wake up, you have implemented picking images. Work on displaying picked images and then sending them
// loading = true;
// messageController.text = '';
if (messageController.text.isNotEmpty ||
xFilesImages.isNotEmpty) {
messageFocusNode.unfocus();
// messageWidgetList.add(sentMessage(
// {"message": messageController.text}));
setState(() {});
print("Sent button clicked");
ApiProvider.sendMessage(
widget.userModel.bearerToken,
widget.senderPhone.phoneNumbers.first,
messageTo,
messageController.text,
xFilesImages);
// loading = false;
messageController.text = '';
xFilesImages = [];
setState(() {});
}
},
child: const Icon(
Icons.send,
size: 30,
color: const Color(0xFF004b77),
),
),
fillColor: AppColors.lightGrey,
hintText: "Enter message...",
hintStyle:
TextStyle(color: AppColors.lightestGrey)),
),
),
),
),
],
),
),
if (loading)
Container(
height: double.infinity,
width: double.infinity,
color: AppColors.lightGrey.withOpacity(0.3),
child: Center(
child: SpinKitChasingDots(
color: AppColors.blue,
)),
)
],
),
);
}
Bad, does not work
static final List<Widget> items= [];
Widget build(BuildContext context) {
return ListView(children: items); // <-- look here
}
Good, does update properly
static final List<Widget> items= [];
Widget build(BuildContext context) {
return ListView(children: [...items]); // <-- look here
}
Grandious with the little extra mile
static final List<Widget> items= [];
Widget build(BuildContext context) {
return ListView(children: <Widget>[...items]); // <-- look here
}
setState needs a brand new object to update properly. It does not look into a List like here if something changed in there.

How can I give message when the text field is same as before?

When the name is already there
Without any change in the text field when clicking its showing
I was trying to update the name in firebase, it was working fine, but each time when I'm clicking edit without any change it's uploading to firebase. I don't want that to happen. Please help me out
Here is my code:
`import 'package:flutter/material.dart';
class EditProfile extends StatefulWidget {
#override
_EditProfileState createState() => _EditProfileState();
}
class _EditProfileState extends State<EditProfile> {
final TextEditingController nameController = TextEditingController();
final _keyChange = GlobalKey<FormState>();
bool btnTextChange = false;
TextEditingController _editingController = TextEditingController(text:"Johny Boy");
String initialText = "Johny Boy";
Widget _editTitleContainer() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
margin: EdgeInsets.only(left: 20,top: 20,bottom: 20),
child: Text(
"Name",
),
),
Container(
decoration: new BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(10.0)),
color: Colors.white,
),
width: MediaQuery.of(context).size.width,
margin: EdgeInsets.symmetric(horizontal: 20),
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 20),
child:
Form(
key: _keyChange,
child: TextField(
enableInteractiveSelection: true,
onSubmitted: (newValue){
setState(() {
initialText = newValue;
});
},
onChanged: (String? value) {
value!.isEmpty ? changeButtonColor(false) : changeButtonColor(true);
},
controller: _editingController,
decoration: InputDecoration(
border: InputBorder.none,
),)
)
),
],
);
}
#override
void dispose() {
_editingController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("sample"),
),
body: SafeArea(
child: Container(
child: Column(
children: [
_editTitleContainer(),
Container(
alignment: Alignment.center,
margin:EdgeInsets.only(top: 20),
child: ElevatedButton(
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 20),
),
onPressed: () {
if (_keyChange.currentState!.validate()) {
_keyChange.currentState!.save();
successMessage();
}
},
child: Text(
"EDIT",
style: TextStyle(
color: Color(0xFF527DAA),
letterSpacing: 1.5,
fontSize: 15,
fontWeight: FontWeight.bold,
fontFamily: 'OpenSans',
),
),
),
),
],
),
),
),
);
}
void successMessage() {
String name = _editingController.text.trim();
if (name.isNotEmpty) {
setState(() {
showDialog(
context: context,
builder: (ctx) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16)),
title: Text("Name Changed Success"),
actions: [
TextButton(
child: Text("Ok"),
onPressed: () {
Navigator.of(ctx).pop();
},
),
],
);
},
);
});
}else {
setState(() {
showDialog(
context: context,
builder: (ctx) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16)),
title: Text("Error!"),
content: Text("Enter Your Name"),
actions: [
TextButton(
child: Text("Close"),
onPressed: () {
Navigator.of(ctx).pop();
},
),
],
);
},
);
});
}
}
}`.
You only need to compare the initial text and the text of _editingController. If they are not the same, then you can update and show successMessage. It will look like this:
ElevatedButton(
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 20),
),
onPressed: () {
if (_keyChange.currentState!.validate()) {
// HERE!
if (initialText != _editingController.text) {
_keyChange.currentState!.save();
successMessage();
}
}
},

how to add flexible height to showGeneralDialog on Flutter?

I added padding for transparent outside. But fixed height. How to change it?
padding: EdgeInsets.fromLTRB(20, 50, 20, 50),
Is it possible to remove above this line and flexible(center)?
I am expected like this flexible height alert. click here
onPressed: () {
showGeneralDialog(
context: context,
barrierColor: Palette.black.withOpacity(.3),
barrierDismissible: true,
transitionDuration: Duration(milliseconds: 400),
pageBuilder: (_, __, ___) {
return ChangePropertyPage(
propertyModel: propertyModel);
},
);
},
change Property Page
class ChangePropertyPage extends StatelessWidget {
final List<PropertyModel> propertyModel;
const ChangePropertyPage({Key key, this.propertyModel}) : super(key: key);
#override
Widget build(BuildContext context) {
final double width = CustomMediaQuery.width(context);
return Padding(
padding: EdgeInsets.fromLTRB(20, 50, 20, 50),
child: Material(
borderRadius: BorderRadius.all(Radius.circular(10)),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
PropertyListTileWidget(
mainTitle: 'USER\'S Name', subTitle: 'USER\'S Email'),
VerticalSpacing(height: 10),
CustomLine(
height: 1,
width: (width - 40) - 20,
color: Palette.black.withOpacity(.2),
),
Expanded(
child: ListView.builder(
itemCount: propertyModel.length,//now length is 1
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return InkWell(
onTap: ()async{
},
child: PropertyListTileWidget(
mainTitle: '${propertyModel[index].propertyName}',
subTitle: '${propertyModel[index].ownerUId}'),
);
}),
)
],
),
),
),
);
}
}
if you are expecting this:
then
full code:
import 'package:flutter/material.dart';
class CustomDialogBox extends StatefulWidget {
#override
_CustomDialogBoxState createState() => _CustomDialogBoxState();
}
class _CustomDialogBoxState extends State<CustomDialogBox> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Custom Dialog Box"),
centerTitle: true,
),
body:Center(
child:FlatButton(
color: Colors.blue,
onPressed: (){
showDialog(
context: (context),
child: ShowCustomDialogBox()
);
},
child: Text("Show Dialog")
)
) ,
);
}
}
class ShowCustomDialogBox extends StatefulWidget {
#override
State<StatefulWidget> createState() => ShowCustomDialogBoxState();
}
class ShowCustomDialogBoxState extends State<ShowCustomDialogBox>with SingleTickerProviderStateMixin {
AnimationController controller;
Animation<double> scaleAnimation;
#override
void initState() {
super.initState();
controller = AnimationController(vsync: this, duration: Duration(milliseconds: 450));
scaleAnimation =CurvedAnimation(parent: controller, curve: Curves.decelerate);
controller.addListener(() {
setState(() {});
});
controller.forward();
}
#override
Widget build(BuildContext context) {
return Center(
child: Material(
color: Colors.transparent,
child: ScaleTransition(
scale: scaleAnimation,
child: Container(
margin: EdgeInsets.all(20.0),
padding: EdgeInsets.all(8.0),
height: MediaQuery.of(context).size.height/2.5, //Change height of dialog box.
width: MediaQuery.of(context).size.width,
decoration: ShapeDecoration(
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0))),
child: Column(
children: <Widget>[
Expanded(
flex: 4,
child: ListView.builder(
itemCount: 10,
itemBuilder: (context, index){
return Column(
// mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text((index+1).toString(),style: TextStyle(color:Colors.blue,fontSize:40),),
Divider()
],
);
}
)
),
Padding(
padding: const EdgeInsets.only(
left: 20.0, right: 10.0, top: 0.0,),
child: ButtonTheme(
height: 35.0,
minWidth: MediaQuery.of(context).size.width/3.5,
child: RaisedButton(
color: Colors.blue,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0)),
splashColor: Colors.white.withAlpha(40),
child: Text(
'Next',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 13.0),
),
onPressed: () {
setState(() {
Navigator.pop(context);
});
},
)
)
),
],
)
),
),
),
);
}
}

Flutter child widget refreshing parent widget - how to not do this

When the class members of child class PartnerInviter are changed inside the child class, somehow it changes the state of the parent class as well which is PartnerConnect. isInviteOption: true, isInviteSent: false => Parent widget resets the flag to false, false. I thing build of PartnerConnect is getting called. How do I fix this?
Parent widget is:
class PartnerConnect extends StatefulWidget{
bool isInviter = true;
#override
State<StatefulWidget> createState() {
return PartnerConnectState();
}
}
class PartnerConnectState extends State<PartnerConnect>{
final _scaffoldKey = GlobalKey<ScaffoldState>();
double card_elevation = 1;
TextEditingController phoneNumber = TextEditingController();
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
key: _scaffoldKey,
body: widget.isInviter ? PartnerInviter(
isInviteOption: false,
isInviteSent: false,
scaffoldKey: _scaffoldKey,
) : PartnerInvitee(
isInvitationAccepted: true,
inviterNumber: '9********0',
scaffoldKey: _scaffoldKey),
appBar: AppBar(
title: Text('Partner Connect'),
backgroundColor: Colors.white,
elevation: 0.0,
),
backgroundColor: Colors.white,
),
);
}
}
Child widget is:
class PartnerInviter extends StatefulWidget{
bool isInviteOption = false;
bool isInviteSent = false;
GlobalKey<ScaffoldState> scaffoldKey;
PartnerInviter({this.isInviteOption, this.isInviteSent, this.scaffoldKey});
#override
State<StatefulWidget> createState() {
return _PartnerInviterState();
}
}
class _PartnerInviterState extends State<PartnerInviter> {
double card_elevation = 1;
TextEditingController phoneNumber = TextEditingController();
#override
Widget build(BuildContext context) {
return inviterConnectBody();
}
Widget inviterConnectBody(){
return Container(
margin: EdgeInsets.all(MediaQuery.of(context).size.width*0.1),
child: ListView(
children: <Widget>[
Visibility(
child: numberInputWidget(),
visible: widget.isInviteOption,
replacement: Container(
child: Visibility(
child: RequestReceivedWidget(phoneNum: phoneNumber.value.text),
visible: widget.isInviteSent,
replacement: Container(
child: RequestRevokeWidget(phoneNum: phoneNumber.value.text),
),
),
),
)
],
),
);
}
Widget RequestRevokeWidget({String phoneNum}){
return Card(
elevation: card_elevation,
color: Colors.deepPurple[50],
child: Container(
height: MediaQuery.of(context).size.height * 0.3,
child: ListView(
children: <Widget>[
ListTile(
title: Text('Partner connected'),
subtitle: Text('Registered number: ${phoneNum}'),
),
Center(
child: Container(
margin: EdgeInsets.only(left: MediaQuery.of(context).size.width * 0.04, right: MediaQuery.of(context).size.width * 0.04),
child: RaisedButton(
color: Colors.deepPurple,
child: Padding(
padding: EdgeInsets.only(bottom: 5),
child: Text('Revoke access', style: TextStyle(color: Colors.white),),),
onPressed: (){
setState(() {
widget.isInviteOption = true;
SnackBar snackBar = SnackBar(content: Text('Partness access successfully revoked'),);
widget.scaffoldKey.currentState.showSnackBar(snackBar);
});
},
),
)),
],
),
),);
}
Widget RequestReceivedWidget({String phoneNum}){
return Card(
elevation: card_elevation,
color: Colors.deepPurple[50],
child: Container(
height: MediaQuery.of(context).size.height * 0.3,
child: ListTile(
title: Text('Waiting for partner to accept invite'),
subtitle: Text('Registered number: ${phoneNum}'),
),
),)
;
}
Widget numberInputWidget(){
final buttonMargin = MediaQuery.of(context).size.width * 0.038;
return Card(
elevation: card_elevation,
color: Colors.deepPurple[50],
child: Container(
height: MediaQuery.of(context).size.height * 0.3,
child: ListView(
children: <Widget>[
ListTile(
title: Text('Partner'),
subtitle: Text('Enter the phone number'),
),
Center(
child: Container(
margin: EdgeInsets.only(left: MediaQuery.of(context).size.width * 0.04, right: MediaQuery.of(context).size.width * 0.04),
child: TextField(
controller: phoneNumber,
keyboardType: TextInputType.number,
enabled: true,
maxLength: 10,
maxLengthEnforced: true,
decoration: InputDecoration(
prefixText: '+91-',
contentPadding: EdgeInsets.only(left: 5.0, bottom: 5.0),
),
),
)),
Padding(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom)),
Container(
margin: EdgeInsets.only(left: buttonMargin, right: buttonMargin),
child: RaisedButton(
color: Colors.deepPurple,
elevation: 0,
padding: EdgeInsets.only(bottom: 5.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0)),
child: Text(
"Confirm & Proceed",
style: TextStyle(
color: Colors.white,
fontFamily: "Nunito",
fontWeight: FontWeight.bold),
),
onPressed: () async {
RegExp regExp = new RegExp(r'(^[0-9]*$)');
if (phoneNumber.text.isEmpty) {
widget.scaffoldKey.currentState.showSnackBar(SnackBar(
content: Text("Please enter the mobile number")));
} else if (!regExp.hasMatch(phoneNumber.text) || phoneNumber.text.length < 10) {
widget.scaffoldKey.currentState.showSnackBar(SnackBar(
content: Text("Please enter valid mobile number")));
} else {
setState(() {
widget.isInviteOption = false;
widget.isInviteSent = true;
});
}
},
),
),
],
),
),)
;
}
}