Flutter rebuild parent widget - flutter

I need help. I have a Dropdown widget in LanguageDropdown class, where the user can select the language. And the widget is inside a settings page widget in Settings class. The language changes on other pages, but not on current one. How can I rebuild that specific page, so the language changes on this one also?
See the code below
import 'package:jptapp/features/settings/change_language/app_localization.dart';
class LanguageDropDown extends StatefulWidget {
#override
_LanguageDropDownState createState() {
return _LanguageDropDownState();
}
}
class _LanguageDropDownState extends State<LanguageDropDown> {
String _value = allTranslations.currentLanguage;
#override
Widget build(BuildContext context) {
return DropdownButton<String>(
items: [
DropdownMenuItem<String>(
child: Text('English'),
value: 'en',
),
DropdownMenuItem<String>(
child: Text('Magyar'),
value: 'hu',
),
DropdownMenuItem<String>(
child: Text('Srpski'),
value: 'rs',
),
],
onChanged: (String value) {
setState(() async{
_value = value;
await allTranslations.setNewLanguage(_value);
});
},
hint: Text(_value),
value: _value,
);
}
}
import 'package:jptapp/core/constants/colors.dart';
import 'package:jptapp/features/settings/change_language/app_localization.dart';
import 'package:jptapp/features/settings/widgets/widgets.dart';
class Settings extends StatefulWidget {
#override
_SettingsState createState() => _SettingsState();
}
class _SettingsState extends State<Settings> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
backgroundColor: MyColors.appBarColor,
title: Text(
allTranslations.text('settings'),
),
),
body: ListView(
children: ListTile.divideTiles(
context: context,
tiles: [
ListTile(
trailing: ThemeChangerAnimationButton(),
title: Text(
allTranslations.text('darkmode'),
),
),
ListTile(
trailing: LanguageDropDown(),
title: Text(
allTranslations.text('language'),
),
),
],
).toList(),
),
);
}
}

I'm not sure this will work but try this:
import 'package:flutter/material.dart';
import 'package:jptapp/features/settings/change_language/app_localization.dart';
class LanguageDropDown extends StatefulWidget {
#override
_LanguageDropDownState createState() {
return _LanguageDropDownState();
}
}
class _LanguageDropDownState extends State<LanguageDropDown> {
String _value = allTranslations.currentLanguage;
#override
Widget build(BuildContext context) {
return DropdownButton<String>(
items: [
DropdownMenuItem<String>(
child: Text('English'),
value: 'en',
),
DropdownMenuItem<String>(
child: Text('Magyar'),
value: 'hu',
),
DropdownMenuItem<String>(
child: Text('Srpski'),
value: 'rs',
),
],
onChanged: (String value) {
setState(() async {
_value = value;
await allTranslations.setNewLanguage(_value);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Settings()
));
});
},
hint: Text(_value),
value: _value,
);
}
}

Related

How to change value on DropdownButton in onChange in Flutter

I am a beginner in the flutter I'm just learning flutter and I am stuck in this code how to solve this please help me?
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget{
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My Application',
home: book(),
);
}
}
class book extends StatefulWidget{
#override
State<StatefulWidget> createState() {
return _bookstate();
}
}
class _bookstate extends State<book>{
String namebook = "";
var writter = ['A','B','C'];
var _currentItemSelected = 'A';
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Stateful Widget'),
),
body: Container(
margin: EdgeInsets.all(20.0),
child: Column(
children:<Widget> [
TextField(
onChanged: (String userInput){
setState(() {
namebook=userInput;
});
},
),
DropdownButton<String>(
items: writter.map((String dropDownStringItem){
return DropdownMenuItem<String>(
value: dropDownStringItem,
child: Text(dropDownStringItem),
);
}).toList(),
onChanged: (String newValueSelected){
setState(() {
this._currentItemSelected = newValueSelected;
});
},
value: _currentItemSelected,
),
Text("Enter book name id $namebook",style: TextStyle(fontSize:20.0),),
],
),
),
);
}
}
and error show this message:
Error: The argument type 'void Function(String)' can't be assigned to the parameter type 'void Function(String?)?' because 'String?' is nullable and 'String' isn't.
You need to follow null safety rules, because your version supports null safety.
Simply change your code;
onChanged: (String? newValueSelected) {
setState(() {
this._currentItemSelected = newValueSelected!;
});
},
And I suggest check and learn what null safety is.
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const Book(),
);
}
}
class Book extends StatefulWidget {
const Book({Key? key}) : super(key: key);
#override
State<StatefulWidget> createState() {
return _Bookstate();
}
}
class _Bookstate extends State<Book> {
String namebook = "";
var writter = ['A', 'B', 'C'];
var _currentItemSelected = 'A';
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Stateful Widget'),
),
body: Container(
margin: const EdgeInsets.all(20.0),
child: Column(
children: <Widget>[
TextField(
onChanged: (String userInput) {
setState(() {
namebook = userInput;
});
},
),
DropdownButton<String>(
items: writter.map((String dropDownStringItem) {
return DropdownMenuItem<String>(
value: dropDownStringItem,
child: Text(dropDownStringItem),
);
}).toList(),
onChanged: (String? newValueSelected) {
setState(() {
_currentItemSelected = newValueSelected!;
});
},
value: _currentItemSelected,
),
Text(
"Enter book name id $namebook",
style: const TextStyle(fontSize: 20.0),
),
],
),
),
);
}
}

How to generate multiple Dropdown dynamically in Flutter?

I have a Java background and new to Flutter. I have stuck in a scenario where I need to create multiple dropdown dynamically. For instance, There is a Pizza deal offers 2 Large pizza, 2 Small pizza and 1 drink. So, Whenever customer select any pizza He/She must need to select a flavor to it. If there is 2 Large pizza what i need to generate is 2 dropdown list with defined flavor so that customer can select 2 different flavor and want to save them in separate variable so that, I can get the value later on, and the same goes for 2 small pizza. In this deal, I have to create 5 dropdown and the quantity of dropdown varies along the deal they offer. How can I achieve this in Flutter?
You can copy paste run full code below
You can use ListView, when add data to List like List<CartItem>, DropdownButton will show
You can for loop List<CartItem> to summary data you need like quantity
code snippet
class _CartWidgetState extends State<CartWidget> {
#override
Widget build(BuildContext context) {
return Row(
children: [
Expanded(child: Pizza(cartItem: widget.cart[widget.index])),
Expanded(child: Flavor(cartItem: widget.cart[widget.index])),
Expanded(
child: IconButton(
icon: Icon(Icons.delete),
onPressed: () {
setState(() {
print(widget.index);
widget.cart.removeAt(widget.index);
widget.callback();
});
...
ListView.builder(
key: UniqueKey(),
itemCount: cart.length,
itemBuilder: (BuildContext ctxt, int index) {
return CartWidget(
cart: cart, index: index, callback: refresh);
}),
output of working demo when click print button
I/flutter (14508): Pizza 1
I/flutter (14508): Pizza 2
I/flutter (14508): Pizza 4
working demo
full code
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
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: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class Flavor extends StatefulWidget {
CartItem cartItem;
Flavor({this.cartItem});
#override
_FlavorState createState() => _FlavorState();
}
class _FlavorState extends State<Flavor> {
String _value = "Flavor 1";
#override
void initState() {
super.initState();
_value = widget.cartItem.flavor;
}
#override
void didUpdateWidget(Flavor oldWidget) {
if (oldWidget.cartItem.flavor != widget.cartItem.flavor) {
_value = widget.cartItem.flavor;
}
super.didUpdateWidget(oldWidget);
}
#override
Widget build(BuildContext context) {
return Container(
child: DropdownButton(
value: _value,
items: [
DropdownMenuItem(
child: Text("Flavor 1"),
value: "Flavor 1",
),
DropdownMenuItem(
child: Text("Flavor 2"),
value: "Flavor 2",
),
DropdownMenuItem(child: Text("Flavor 3"), value: "Flavor 3"),
DropdownMenuItem(child: Text("Flavor 4"), value: "Flavor 4")
],
onChanged: (value) {
setState(() {
_value = value;
widget.cartItem.flavor = value;
});
}),
);
}
}
class Pizza extends StatefulWidget {
CartItem cartItem;
Pizza({this.cartItem});
#override
_PizzaState createState() => _PizzaState();
}
class _PizzaState extends State<Pizza> {
String _value = "";
#override
void initState() {
super.initState();
_value = widget.cartItem.itemName;
}
#override
void didUpdateWidget(Pizza oldWidget) {
if (oldWidget.cartItem.itemName != widget.cartItem.itemName) {
_value = widget.cartItem.itemName;
}
super.didUpdateWidget(oldWidget);
}
#override
Widget build(BuildContext context) {
return Container(
child: DropdownButton(
value: _value,
items: [
DropdownMenuItem(
child: Text("Pizza 1"),
value: "Pizza 1",
),
DropdownMenuItem(
child: Text("Pizza 2"),
value: "Pizza 2",
),
DropdownMenuItem(child: Text("Pizza 3"), value: "Pizza 3"),
DropdownMenuItem(child: Text("Pizza 4"), value: "Pizza 4")
],
onChanged: (value) {
setState(() {
_value = value;
widget.cartItem.itemName = value;
});
}),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class CartItem {
String productType;
String itemName;
String flavor;
CartItem({this.productType, this.itemName, this.flavor});
}
class CartWidget extends StatefulWidget {
List<CartItem> cart;
int index;
VoidCallback callback;
CartWidget({this.cart, this.index, this.callback});
#override
_CartWidgetState createState() => _CartWidgetState();
}
class _CartWidgetState extends State<CartWidget> {
#override
Widget build(BuildContext context) {
return Row(
children: [
Expanded(child: Pizza(cartItem: widget.cart[widget.index])),
Expanded(child: Flavor(cartItem: widget.cart[widget.index])),
Expanded(
child: IconButton(
icon: Icon(Icons.delete),
onPressed: () {
setState(() {
print(widget.index);
widget.cart.removeAt(widget.index);
widget.callback();
});
},
),
)
],
);
}
}
class _MyHomePageState extends State<MyHomePage> {
List<CartItem> cart = [];
void refresh() {
setState(() {});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: ListView.builder(
key: UniqueKey(),
itemCount: cart.length,
itemBuilder: (BuildContext ctxt, int index) {
return CartWidget(
cart: cart, index: index, callback: refresh);
}),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
RaisedButton(
onPressed: () {
cart.add(CartItem(
productType: "pizza",
itemName: "Pizza 1",
flavor: "Flavor 1"));
setState(() {});
},
child: Text("add Pizza"),
),
RaisedButton(
onPressed: () {
for (int i = 0; i < cart.length; i++) {
print(cart[i].itemName);
}
},
child: Text("Print Pizza"),
),
],
)
],
),
),
);
}
}
You can use collection-if in your UI code to show those dropdowns when a certain condition is met.
Widget build() {
return Column(
children: [
pizzaSelector(),
if (pizzaIsSelected)
flavorSelector(),
]
);
}
Andrea has a good video explaining collection-if and spread operators which I think will help you.

Change DropdownButtonFormField value programmatically

I'm trying to change the DropdownButtonFormField value on event (button press for example) using setState. But it's not working.
Note: it works in case I use DropdownButton, but with DropdownButtonFormField it's not responding.
Here is a simple code showing what I'm trying to implement.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Testing(),
);
}
}
class Testing extends StatefulWidget {
#override
_TestingState createState() => _TestingState();
}
class _TestingState extends State<Testing> {
String selectedValue;
#override
Widget build(BuildContext context) {
return Material(
child: Column(
children: <Widget>[
DropdownButtonFormField(
value: selectedValue,
items: ['one', 'two'].map((value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
onChanged: (value) {
setState(() {
selectedValue = value;
});
},
),
RaisedButton(
child: Text('test'),
onPressed: (){
setState(() {
selectedValue = 'two';
});
},
),
],
),
);
}
}
Define instance variable from Global Key and pass it to DropdownButtonFormField
final dropdownState = GlobalKey<FormFieldState>();
You can change the value of dropDownFieldItem by calling this method
dropdownState.currentState.didChange('two');
final code:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Testing(),
);
}
}
class Testing extends StatefulWidget {
#override
_TestingState createState() => _TestingState();
}
class _TestingState extends State<Testing> {
String selectedValue;
final dropdownState = GlobalKey<FormFieldState>();
#override
Widget build(BuildContext context) {
return Material(
child: Column(
children: <Widget>[
DropdownButtonFormField(
key: dropdownState,
value: selectedValue,
items: ['one', 'two'].map((value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
onChanged: (value) {
setState(() {
selectedValue = value;
});
},
),
RaisedButton(
child: Text('test'),
onPressed: () {
dropdownState.currentState.didChange('one');
},
),
],
),
);
}
}
Here working normally with DropdownButtonFormField and DropdownButton.
flutter --version
Flutter 1.12.13+hotfix.9 • channel stable •
In Flutter version 1.17.2 that bug was fixed, so be sure to upgrade.
Github issue: https://github.com/flutter/flutter/issues/56898
Fixed in version 1.17.2: https://github.com/flutter/flutter/wiki/Hotfixes-to-the-Stable-Channel#1172-may-28-2020

can anyone help me with where to place a submit button in this flutter code i dont seem to be getting it?

import 'package:flutter/material.dart';
class CheckBoxInListview extends StatefulWidget {
#override
_CheckBoxInListviewState createState() => _CheckBoxInListviewState();
}
class _CheckBoxInListviewState extends State<CheckBoxInListview> {
bool _isChecked = true;
List<String> _texts = ["Movies", "Music", "Exercise", "Games"];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Select likes to proceed with registration"),
backgroundColor: Colors.blue,
),
body: ListView(
padding: EdgeInsets.all(8.0),
children: _texts
.map((text) => CheckboxListTile(
title: Text(text),
value: _isChecked,
onChanged: (val) {
setState(() {
_isChecked = val;
});
},
))
.toList(),
),
);
}
}
You can customize floatingActionButton as you want:
class _CheckBoxInListviewState extends State<CheckBoxInListview> {
bool _isChecked = true;
List<String> _texts = ["Movies", "Music", "Exercise", "Games"];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Select likes to proceed with registration"),
backgroundColor: Colors.blue,
),
body: ListView(
padding: EdgeInsets.all(8.0),
children: _texts
.map((text) => CheckboxListTile(
title: Text(text),
value: _isChecked,
onChanged: (val) {
setState(() {
_isChecked = val;
});
},
))
.toList(),
),
floatingActionButton: RaisedButton(onPressed: null),
);
}
}

How to onClick listener on DropdownMenuItem

I have build the code of DropdownMenuItem, now when i click an item from dropdownmenuitem it should move to another screen.Below is the code
class TimesScreen extends StatefulWidget {
#override
_TimesScreenState createState() => _TimesScreenState();
}
class _TimesScreenState extends State<TimesScreen> {
var gender;
#override
Widget build(BuildContext context) {
DropdownButton(
hint: Text("Select",
style: TextStyle(color: Colors.white),),
onChanged: (val){
setState(() {
this.gender=val;
});
},
value: this.gender,
items: [
DropdownMenuItem(
//onTap:
value: 'Earth',
child: Text('Earth'
),
),
DropdownMenuItem(
//onTap:
value: 'Mars',
child: Text('Mars'
),
),)]
You can wrap your Text widget with GestureDetector to which has an onTap function which you can use to execute your desired code. For more details look at this: https://api.flutter.dev/flutter/widgets/GestureDetector-class.html
This should work:
DropdownMenuItem(
value: 'Earth',
child: GestureDetector(
onTap: () {
// navigate code...
},
child: Text('Earth')
),
),
After applying fayeed's solution, I noticed that this only makes the text inside the dropdown clickable. To fix this, you can simply use DropdownButton.onChanged.
Full widget:
class TimesScreen extends StatefulWidget {
#override
_TimesScreenState createState() => _TimesScreenState();
}
class _TimesScreenState extends State<TimesScreen> {
var gender;
#override
Widget build(BuildContext context) {
return DropdownButton(
hint: Text("Select"),
value: this.gender,
items: [
DropdownMenuItem(value: 'Earth', child: Text('Earth')),
DropdownMenuItem(value: 'Mars', child: Text('Mars')),
],
onChanged: (val) {
setState(() {
this.gender = val;
});
switch (val) {
case 'Earth':
Navigator.pushNamed(context, '/earth_target_page');
break;
case 'Mars':
Navigator.pushNamed(context, '/mars_target_page');
break;
}
},
);
}
}