I'm quite new to flutter and dart.
as an exercise I'm trying to create a Coffeeshop application user interface. here I want to update an integer variable in a StatefulWidget from an other StatefulWidget. I've tried the setState((){}) but It seems that the setState only can update its parent StatefulWidget variables. I've also tried to use Global variables but nothing change.
the Interesting thing is that when the Keyboard opens, the mentioned variable gets updated!! the keyboard opens from a Textfield inside the app, but I don't know how they are related to each other!!
I want to Update "menu_index" which belongs to MainPage StatefulWidget , from CoffeeType StatefulWidget.
List MenuList = <Widget>[Cappucinno(),Americano()] ;
int menu_index=0;
class MainPage extends StatefulWidget {
const MainPage({Key? key}) : super(key: key);
@override
State<MainPage> createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
@override
Widget build(BuildContext context) {
return MyScaffold(
body: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Center(
child: AutoSizeText(
"Find the best coffee for you!",
maxLines: 1,
style: GoogleFonts.lato(
textStyle: TextStyle(
fontSize: 30,
fontWeight: FontWeight.w900,
),
),
),
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.03,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: TextField(
decoration: InputDecoration(
prefixIcon: Icon(Icons.search),
hintText: "Search Coffe",
border: OutlineInputBorder(),
counter: Offstage(),
),
),
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.03,
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.05,
child: CoffeeType(),
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.01,
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.37,
child: MenuList[menu_index],
)
],
),
));
}
}
class CoffeeType extends StatefulWidget {
@override
State<CoffeeType> createState() => _CoffeeTypeState();
}
class _CoffeeTypeState extends State<CoffeeType> {
List type = <String>[
"Coppuccino",
"Americano",
"Latte",
"Espresso",
"Arabics",
"Decaf",
"Macchiato",
"Cortado"
];
int selectedindex=0;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 8,
itemBuilder: (context, index){
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: GestureDetector(
onTap: (){
setState((){
selectedindex = index;
menu_index = selectedindex;
print(menu_index);
});
},
child: Text(
type[index],
style: GoogleFonts.lato(
textStyle: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
color: selectedindex == index ? Colors.deepOrange : Colors.white,
),
)
),
),
);
}
),
);
}
}
CodePudding user response:
You can use a callback method to update parent widget.
class CoffeeType extends StatefulWidget {
final Function(int) onTap;
const CoffeeType({
Key? key,
required this.onTap,
}) : super(key: key);
@override
State<CoffeeType> createState() => _CoffeeTypeState();
}
class _CoffeeTypeState extends State<CoffeeType> {
child: GestureDetector(
onTap: () {
setState(() {
selectedindex = index;
menu_index = selectedindex;
print(menu_index);
});
widget.onTap(menu_index); //here passing tap index to the parent widget
},
And recive here
child: CoffeeType(
onTap: (p0) {
print(p0);
setState(() {});
},
),