Setstate for statless widget dropdownButton from a stateful parent - flutter

I have three widgets first one is LightBulb(stateless) that have some color properties. The second one is widget named as LightColorSelector(stateless) that has a DropdownMenu with string type items Red, Greenand Blue. And, the third class is Classroom(stateful widget) which is the parent of that two classes. My aim is to set the states from that class.
I need to set a list of that three colors inside the Classroom, when someone clicks on one of the LightColorSelector items the LightBulb should switches according to clicked color. However, the color inside the LightBulb returns always null. I think it didn't set. Actually, I might know where is the mistake. I think in the LightColorSelector function there is a onChanged property and I didn't set the value into the func(). I marked below where I suspect the mnistake is occur.
import 'package:flutter/material.dart';
// ignore: must_be_immutable
class LightBulb extends StatelessWidget {
bool isLit;
Color color;
LightBulb(bool isLit, Color color) {
this.isLit = isLit;
this.color = color;
print(color.toString());
}
Widget build(BuildContext context) {
return Container(
color: isLit ? color : Colors.red,
padding: EdgeInsets.all(5),
child: isLit ? Text('ON') : Text('OFF'),
);
}
}
class LightButton extends StatelessWidget {
Function func;
bool isLightOn;
LightButton(Function func, bool iSLightOn) {
this.func = func;
this.isLightOn = iSLightOn;
}
String title() {
if (isLightOn) return "Turn light off";
return "Turn light on";
}
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.symmetric(vertical: 4, horizontal: 12),
color: Colors.red,
child: Container(
color: Colors.blue,
child: MaterialButton(
textColor: Colors.white,
onPressed: () => func(),
child: Text(
title(),
style: TextStyle(color: Colors.white),
),
),
),
);
}
}
class Classroom extends StatefulWidget {
#override
_ClassroomState createState() => _ClassroomState();
}
class _ClassroomState extends State<Classroom> {
bool isLightOn = false;
String title = "Not set yet";
List<Color> lightColor = [Colors.red, Colors.green, Colors.blue];
Color color;
String value;
selectLightColor() {
setState(() {
if (value == 'Red') color = lightColor[0];
if (value == 'Green') color = lightColor[1];
if (value == 'Blue')
color = lightColor[2];
else
color = Colors.amber;
});
}
onButtonPressed() {
setState(() {
isLightOn = !isLightOn;
});
}
#override
Widget build(BuildContext context) {
return Center(
child: Container(
color: Colors.blue,
padding: EdgeInsets.all(5),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
LightBulb(isLightOn, color),
LightButton(onButtonPressed, isLightOn),
LightColorSelector(selectLightColor),
],
),
),
);
}
}
class LightColorSelector extends StatelessWidget {
String initialVal = 'Red';
Function func;
LightColorSelector(Function func) {
this.func = func;
}
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(10),
child: DropdownButton(
value: initialVal,
onChanged: (value) => func, // =========== Here the error occurs ==========================
items: <String>['Red', 'Green', 'Blue']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
));
}
}
Sample output,

You can copy paste run full code below
Step 1: Set initial value in _ClassroomState
class _ClassroomState extends State<Classroom> {
..
Color color = Colors.red;
String value = 'Red';
Step 2: Callback function selectLightColor need parameter selectedValue and use if else if, you have logic error here
selectLightColor(String selectedValue) {
setState(() {
value = selectedValue;
if (selectedValue == 'Red') {
color = lightColor[0];
} else if (selectedValue == 'Green') {
color = lightColor[1];
} else if (selectedValue == 'Blue')
color = lightColor[2];
else
color = Colors.amber;
});
}
Step 3: LightColorSelector constructor and onChanged need to set initialVal and onChanged need to call func(value);
class LightColorSelector extends StatelessWidget {
String initialVal;
Function func;
LightColorSelector(Function func, String value) {
this.func = func;
this.initialVal = value;
}
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(10),
child: DropdownButton<String>(
value: initialVal,
onChanged: (value) {
initialVal = value;
func(value);
},
working demo
full code
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,
),
home: Scaffold(body: Classroom()),
);
}
}
// ignore: must_be_immutable
class LightBulb extends StatelessWidget {
bool isLit;
Color color;
LightBulb(bool isLit, Color color) {
this.isLit = isLit;
this.color = color;
print(color.toString());
}
Widget build(BuildContext context) {
return Container(
color: isLit ? color : Colors.red,
padding: EdgeInsets.all(5),
child: isLit ? Text('ON') : Text('OFF'),
);
}
}
class LightButton extends StatelessWidget {
Function func;
bool isLightOn;
LightButton(Function func, bool iSLightOn) {
this.func = func;
this.isLightOn = iSLightOn;
}
String title() {
if (isLightOn) return "Turn light off";
return "Turn light on";
}
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.symmetric(vertical: 4, horizontal: 12),
color: Colors.red,
child: Container(
color: Colors.blue,
child: MaterialButton(
textColor: Colors.white,
onPressed: () => func(),
child: Text(
title(),
style: TextStyle(color: Colors.white),
),
),
),
);
}
}
class Classroom extends StatefulWidget {
#override
_ClassroomState createState() => _ClassroomState();
}
class _ClassroomState extends State<Classroom> {
bool isLightOn = false;
String title = "Not set yet";
List<Color> lightColor = [Colors.red, Colors.green, Colors.blue];
Color color = Colors.red;
String value = 'Red';
selectLightColor(String selectedValue) {
setState(() {
value = selectedValue;
if (selectedValue == 'Red') {
color = lightColor[0];
} else if (selectedValue == 'Green') {
color = lightColor[1];
} else if (selectedValue == 'Blue')
color = lightColor[2];
else
color = Colors.amber;
});
}
onButtonPressed() {
setState(() {
isLightOn = !isLightOn;
});
}
#override
Widget build(BuildContext context) {
return Center(
child: Container(
//color: Colors.blue,
padding: EdgeInsets.all(5),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
LightBulb(isLightOn, color),
LightButton(onButtonPressed, isLightOn),
LightColorSelector(selectLightColor, value),
],
),
),
);
}
}
class LightColorSelector extends StatelessWidget {
String initialVal;
Function func;
LightColorSelector(Function func, String value) {
this.func = func;
this.initialVal = value;
}
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(10),
child: DropdownButton<String>(
value: initialVal,
onChanged: (value) {
initialVal = value;
func(value);
},
items: <String>['Red', 'Green', 'Blue']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
));
}
}

StatelessWidget doesn't have a state so you can't set state in stateless widget, this is why it called stateless. If you want to set state you need to use stateful widget

Related

how to show two widgets one after another within some time interval in dart

I am trying to show two widgets one after another within 2 seconds of time interval.
Here, First I am trying to show the text widget and after two seconds of time interval it should be change to dot widget.
I tried but I am unable to do this. I was stuck how to return the two widgets at a time one after another.
code:
Widget _getNumberWidget(bool hasHighlight, Color color, String text) {
final textStyle = context.appThemeData.passcodeFieldStyle.numberTextStyle.textStyle.copyWith(color: color);
return Container(
height: 35,
alignment: Alignment.bottomCenter,
child: FittedBox(
fit: BoxFit.fitHeight,
child: text.isEmpty ? _getDotWidget(hasHighlight, color, text) : _showChar(hasHighlight, color, text),
),
);
}
Widget _showChar(bool hasHighlight, Color color, String text) {
final textStyle = context.appThemeData.passcodeFieldStyle.numberTextStyle.textStyle.copyWith(color: color);
AppText(
text: text,
style: context.appThemeData.passcodeFieldStyle.numberTextStyle.copyWith(textStyle: textStyle),
);
sleep(const Duration(seconds: 2));
return _getDotWidget(hasHighlight, color, text);
}
If I return the Apptext then the remaining two lines code will change to dead code. Can any one suggest me how to do this. Thanks
Use state, define variable:
bool _showDotWidget = false;
Instead of sleep, use Future.delayed
Widget _showChar(bool hasHighlight, Color color, String text) {
if (_showDotWidget)
return _getDotWidget(hasHighlight, color, text);
else {
Future.delayed(Duration(seconds:2), () {
setState({
_showDotWidget = true;
});
});
final textStyle = context.appThemeData.passcodeFieldStyle.numberTextStyle.textStyle.copyWith(color: color);
return AppText(
text: text,
style: context.appThemeData.passcodeFieldStyle.numberTextStyle.copyWith(textStyle: textStyle),
);
}
}
Check my simple implementation using Future.delayed, which fires setState after 5 seconds to set a value (isElapsed=true).
class _ShowWidgetsState extends State<ShowWidgets> {
bool isElapsed = false;
#override
Widget build(BuildContext context) {
//Delay for 5 seconds before setting
//isElapsed to true
Future.delayed(Duration(seconds: 5), () {
print('Displaying');
setState(() {
isElapsed = true;
});
});
return Scaffold(
appBar: AppBar(
title: Text('Show Widgets'),
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {},
child: Text('First Widget'),
),
SizedBox(height: 10.0),
Container(
alignment: Alignment.center,
//Use Visibility Widget to show
child: Visibility(
visible: isElapsed,
child: ElevatedButton(
child: Text('Second Widget'),
onPressed: () {},
),
)),
],
),
);
}
You can use FutureBuilder like this
import 'package:flutter/material.dart';
class ShowWidgetWithInterval extends StatelessWidget {
Future<bool> _setInterval() async {
await Future.delayed(Duration(seconds: 2));
return true;
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: _setInterval(),
builder: (context, intervalSnapshot) {
if (!intervalSnapshot.hasData) {
return Text('Widget 1');
}
return Text('Widget 2');
},
);
}
}
You can use FutureBuilder and customize StatelessWidget insead of a function:
FutureBuilder(
future: Future.delayed(const Duration(seconds: 3)),
builder: (c, s) => s.connectionState == ConnectionState.done
? Text("Dot widget with text: $text")
// Pass here SizedBox.shrink(); in case you do not want to render anithing
: const Text("Dot widget is loading..."));
Full code to reproduce:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String? text;
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Material App',
home: Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
text = 'Some text';
});
},
),
body: Center(
child: Container(
padding: const EdgeInsets.all(4),
color: Colors.lightGreen, child: NumberWidget(text: text))),
),
);
}
}
class NumberWidget extends StatelessWidget {
final bool hasHighlight;
final Color color;
final String? text;
const NumberWidget(
{Key? key,
this.hasHighlight = false,
this.color = Colors.lightGreen,
this.text})
: super(key: key);
//Helper function for a text variable.
bool isEmpty(String? s) => s == null || s.trim().isEmpty;
#override
Widget build(BuildContext context) {
if (isEmpty(text)) {
return const Text("Text is empty");
}
return FutureBuilder(
future: Future.delayed(const Duration(seconds: 3)),
builder: (c, s) => s.connectionState == ConnectionState.done
? Text("Dot widget with text: $text")
// Pass here SizedBox.shrink(); in casde you do not want to render anithing
: const Text("Dot widget is loading..."));
}
}
Result:

How to change the color of a Widget based on a different Widget?

I'm trying to make simple app which displays SvgPicture.assets() and user can change the color of the SvgPicture() using color picker.
I have 2 widgets:
for displaying SvgPicture() called it Svg.dart
main.dart contains BottomNavigationView, and one of the tabs opens color picker, and the Svg.dart
I encountered some errors with setState(() {}) but I managed to fix the error somehow but it does not change the color, when I tried changing the background color of main.dart it worked perfectly.
here is my code:
onItemTap() method for the BottomNavigationBar
void _onItemTap(int index) {
setState(() {
if (index == 0) {
// First Tab
}
if (index == 1) {
// SecondTab
}
if (index == 2) {
// Third Tab
}
if (index == 3) {
showDialog(
context: context,
builder: (BuildContext context){
return AlertDialog(
content:
SingleChildScrollView(
child: new ColorPicker(
pickerColor: Colors.red,
onColorChanged: (Color colorChanged) {
color = colorChanged;
// (color) is assigned default value of Colors.red
// here I'm trying to assign new value to (color)
},
),//ColorPicker
),//SingleChildScrollView
);//AlertDialog
});
}
});
}
then in Svg.dart I made another variable Color picked = Colors.red and assigned red as default value. this is how the Svg.dart widget code looks like:
Widget build(BuildContext context) {
setState(() {
picked = main().createState().color;
});
return CustomMultiChildLayout(
delegate: TempDelegate(
position: Offset.zero
),
children: [
buildLayoutId(ids.shirtId, MyConstants.shirt, picked)
],
);
}
LayoutId buildLayoutId(Object id, String item, Color color) {
return LayoutId(
id: id,
child: SvgPicture.asset(
item,
color: color,
),
);
}
I tried looking for flutter documentations but I don't really know how/where the issue is, and did not find tutorials, Please help
EDIT
this is the main.dart
class Main extends StatefulWidget{
#override
_MainState createState() => _MainState();
}
class _Main extends State<Main> {
int _slectedIndex = 0;
Color color = MyConstants.darkWhite;
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: Center(
child: Svg(),
),
bottomNavigationBar: BottomNavigationBar(
items: const<BottomNavigationBarItem>[
BottomNavigationBarItem(
label: "",
icon: Icon(Icons.home),
),
BottomNavigationBarItem(
label: "",
icon: Icon(Icons.home),
),
BottomNavigationBarItem(
label: "",
icon: Icon(Icons.home),
),
BottomNavigationBarItem(
label: "",
icon: Icon(Icons.home),
),
],
onTap: _onItemTap,
),
);
}
void _onItemTap(int index) {
setState(() {
if (index == 0) {
// do something
}
if (index == 1) {
// do something
}
if (index == 2) {
// do something
}
if (index == 3) {
showDialog(
context: context,
builder: (BuildContext context){
return AlertDialog(
content:
SingleChildScrollView(
child: new ColorPicker(
pickerColor: Colors.red,
onColorChanged: (Color colorChanged) {
setState(() {
color = colorChanged;
});
},
),
),
);
});
}
});
}
}
and Svg.dart
class Svg extends StatefulWidget{
//Color picked;
#override
SvgState createState() => Svg();
}
class SvgState extends State<Svg> {
#override
Widget build(BuildContext context) {
return CustomMultiChildLayout(
delegate: SvgDelegate(
position: Offset.zero
),
children: [
buildLayoutId(ids.shirtId, MyConstants.shirt, CreateKit().createState().color)
],
);
}
LayoutId buildLayoutId(Object id, String item, Color color) {
return LayoutId(
id: id,
child: SvgPicture.asset(
item,
color: color,
),
);
}
}
the class that extends MultiChildLyoutDelegate for CustomMultichildLayout in Svg.dart
class SvgDelegate extends MultiChildLayoutDelegate{
final Offset position;
SvgDelegate({
this.position
});
#override
void performLayout(Size size) {
Size leadSize = Size.zero;
itemLayout(leadSize, size, ids.shirtId);
}
void itemLayout(Size leadSize, Size size, Object id) {
if(hasChild(id)){
leadSize = layoutChild(
id,
BoxConstraints.loose(size),
);
}
}
#override
bool shouldRelayout(TempDelegate oldDelegate) {
return oldDelegate.position != position;
}
}
In Flutter everything is a widget and you can create your own custom widgets.
Likewise, there are concepts such as hierarchy and state.
A stateless widget is a StatelessWidget such as a label, a background, a title or whatever.
A stateful widget is a StatefulWidget is something that changes such as a switch, an animated background, a page, etc. There is also an InheritedWidget but that is another topic.
setState is used in the StatefulWidget to update the state of that widget, to update a child from the parent, you can use the properties of the child.
When setState is called, it rebuilds the widget and its children if necessary.
The Container widget has a color property.
Container(
color: colorParent,
)
Your custom widget can also have any property such as color or size or colorChild.
ChildWidget(
colorChild: colorParent,
)
When you want to access the colorChild property of a StatefulWidget you use widget.colorChild, when it has no state, you can simply use colorChild.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark(),
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(),
body: Center(
child: Parent(),
),
),
);
}
}
class Parent extends StatefulWidget {
#override
ParentState createState() => ParentState();
}
class ParentState extends State<Parent> {
// Define the color in parent
Color colorParent = Colors.red;
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Center(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
// Pass the color as a property
ChildWidget(colorChild: colorParent),
VerticalDivider(color: colorParent),
Child2Widget(colorChild: colorParent),
],
),
),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
label: "Tap to Blue",
icon: Icon(Icons.home),
),
BottomNavigationBarItem(
label: "Tap to Orange",
icon: Icon(Icons.dashboard),
),
BottomNavigationBarItem(
label: "Tap to Green",
icon: Icon(Icons.palette),
),
// ...
],
onTap: _onItemTap,
),
);
}
void _onItemTap(index) {
// ...
switch (index) {
case 0:
setState(() {
// Update color in parent
colorParent = Colors.blue;
});
break;
case 1:
setState(() {
colorParent = Colors.orange;
});
break;
case 2:
setState(() {
colorParent = Colors.green;
});
break;
}
}
}
class ChildWidget extends StatefulWidget {
// Define color in child
final Color colorChild;
const ChildWidget({Key key, this.colorChild}) : super(key: key);
#override
ChildWidgetState createState() => ChildWidgetState();
}
class ChildWidgetState extends State<ChildWidget> {
#override
Widget build(BuildContext context) {
return Container(
height: 100,
width: 100,
// Use it
color: widget.colorChild,
child: Text('Child 1'),
);
}
}
class Child2Widget extends StatelessWidget {
// Define color in child
final Color colorChild;
const Child2Widget({Key key, this.colorChild}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
height: 100,
width: 100,
// Use it
color: colorChild,
child: Text('Child 2'),
);
}
}
please change the default picker color value, please assign the variable that contains any color value, and onTabItem change the value of the variable.
Color _color = Colors.red;
ColorPicker(pickerColor: _color, onColorChanged: (Color colorChanged) { setState(() => _color = colorChanged;},),

how to pass from object state to object and then pass it to another screen

I need your help,
At first I have two pages, both of them are stateful widget, one of them is the main screen, 2nd page has data and i want to pass it to the main screen
mainpage
code
#override
_PriceScreenState createState() => _PriceScreenState();
}
class _PriceScreenState extends State<PriceScreen> {
String selectedCurrency = 'USD';
String bitcoinValueInUSD;
int dropNumber;
void getCurrenciesBitcoin() async {
try {
CoinData coinData = CoinData();
double usdPrice = await coinData.getCurrencies();
setState(() {
bitcoinValueInUSD = usdPrice.toStringAsFixed(0);
});
} catch (e) {
print(e);
}
}
#override
Widget build(BuildContext context) {
getCurrenciesBitcoin();
return Scaffold(
appBar: AppBar(
title: Text('🤑 Coin Ticker'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Padding(
padding: EdgeInsets.fromLTRB(18.0, 18.0, 18.0, 0),
child: Card(
color: Colors.lightBlueAccent,
elevation: 5.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
child: Padding(
padding: EdgeInsets.symmetric(vertical: 15.0, horizontal: 28.0),
child: Text(
'1 BTC = $bitcoinValueInUSD $selectedCurrency',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20.0,
color: Colors.white,
),
),
),
),
),
Container(
height: 150.0,
alignment: Alignment.center,
padding: EdgeInsets.only(bottom: 30.0),
color: Colors.lightBlue,
child: GetDropDownMenu(
selectedCurrency: ,
),
),
],
),
);
}
}
and this is the second page
class GetDropDownMenu extends StatefulWidget {
#override
_GetDropDownMenuState createState() => _GetDropDownMenuState();
}
class _GetDropDownMenuState extends State<GetDropDownMenu> {
String selectedCurrency;
List<DropdownMenuItem<String>> getDropDownItem() {
List<DropdownMenuItem<String>> dropDownItems = [];
for (String currency in currenciesList) {
var newItem = DropdownMenuItem(
child: Text(currency),
value: currency,
);
dropDownItems.add(newItem);
}
return dropDownItems;
}
#override
Widget build(BuildContext context) {
return DropdownButton<String>(
value: selectedCurrency,
items: getDropDownItem(),
onChanged: (value) {
setState(() {
selectedCurrency = value;
});
});
}
}
, what i need is to pass the selectedCurrency value from 2nd page to the main page to be equal selectedCurrency variable there
You can add callback function in the constructor to return the dropdown value.
For example
class GetDropDownMenu extends StatefulWidget {
final Function(String) onSubmitted;
const GetDropDownMenu({Key key, this.onSubmitted}) : super(key: key);
#override
_GetDropDownMenuState createState() => _GetDropDownMenuState();
}
class _GetDropDownMenuState extends State<GetDropDownMenu> {
String selectedCurrency;
#override
Widget build(BuildContext context) {
return DropdownButton<String>(
value: selectedCurrency,
items: getDropDownItem(),
onChanged: (value) {
setState(() {
selectedCurrency = value;
});
widget.onSubmitted(value);
});
}
}
How to use:
GetDropDownMenu(
onSubmitted: (val) {
print("Result value on dropdown: $val");
},
)
The easiest way:
1. From 1st Screen navigate to others as:
Navigator.pushNamed(context, "second",arguments: selectedCurrency);
},
2. On Second Screen in build method get as :
#override
Widget build(BuildContext context) {
var passedValue = ModalRoute.of(context).settings.arguments;
return Scaffold(
appBar: AppBar(title: Text("Second")),
body: Container(
child: Column(
children: <Widget>[
Text("PassedValue : $passedValue"),
],
),
),
);
}
Hope it will be useful

how Can i make this Single selection Flutter?

I have an Apps which is having a listview with the reaction button in a flutter . I want to make this when a user clicked any of this love icon then it's filled with red color.
enter image description here
enter image description here
Like this image but the problem is when I clicked one of this love icon all of the icons turned into red color but I only want to change the color of love of icon which one is Selected.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool like;
#override
List<String> user = ['Dipto', 'Dipankar', "Sajib", 'Shanto', 'Pranto'];
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('ListView Demu'),
),
body: Center(
child: Container(
child: ListView.builder(
itemCount: user.length,
itemBuilder: (context, index) {
return Container(
padding: EdgeInsets.all(10),
height: 50,
width: MediaQuery.of(context).size.width * 0.8,
color: Colors.yellowAccent,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
user[index],
),
Positioned(
child: IconButton(
icon: _iconControl(like),
onPressed: () {
if (like == false) {
setState(() {
like = true;
_iconControl(like);
});
} else {
setState(() {
like = false;
_iconControl(like);
});
}
},
),
),
],
),
);
},
),
)),
);
}
_iconControl(bool like) {
if (like == false) {
return Icon(Icons.favorite_border);
} else {
return Icon(
Icons.favorite,
color: Colors.red,
);
}
}
}
I also try with using parameter but Its failed Like that :
child: IconButton(
icon: _iconControl(true),
onPressed: () {
if (false) {
setState(() {
_iconControl(true);
});
} else {
setState(() {
_iconControl(false);
});
}
},
),
Can you help me Please. Thanks in advance
You can create a modal class to manage the selection of your list
Just create a modal class and add a boolean variable to maintaining selection using. that boolean variable
SAMPLE CODE
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool like;
List<Modal> userList = List<Modal>();
#override
void initState() {
userList.add(Modal(name: 'Dipto', isSelected: false));
userList.add(Modal(name: 'Dipankar', isSelected: false));
userList.add(Modal(name: 'Sajib', isSelected: false));
userList.add(Modal(name: 'Shanto', isSelected: false));
userList.add(Modal(name: 'Pranto', isSelected: false));
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('ListView Demu'),
),
body: Center(
child: Container(
child: ListView.builder(
itemCount: userList.length,
itemBuilder: (context, index) {
return Container(
padding: EdgeInsets.all(10),
height: 50,
width: MediaQuery
.of(context)
.size
.width * 0.8,
color: Colors.yellowAccent,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
userList[index].name,
),
Positioned(
child: IconButton(
icon: _iconControl( userList[index].isSelected),
onPressed: () {
setState(() {
userList.forEach((element) {
element.isSelected = false;
});
userList[index].isSelected = true;
});
},
),
),
],
),
);
},
),
)),
);
}
_iconControl(bool like) {
if (like == false) {
return Icon(Icons.favorite_border);
} else {
return Icon(
Icons.favorite,
color: Colors.red,
);
}
}
}
class Modal {
String name;
bool isSelected;
Modal({this.name, this.isSelected = false});
}

How can I change DropdownButton values from another widget in Flutter?

I am using that DropdownButton inside of the Stateless wigdet but I want to change that DropdownButton values from another Stateful widget. Likewise with using DropdownButton value, I want to change another stateless widget's container color.
Here is my First Stateless widget
List<String> dropdownValues = ['red', 'green', 'blue'];
#override
Widget build(BuildContext context) {
return Container(
child: DropdownButton(
items: dropdownValues
.map((value) => DropdownMenuItem(
child: Text(value),
value: value,
))
.toList(),
onChanged: (String newValue) {},
isExpanded: false,
hint: Text('Chose Color'),
selectedItemBuilder: ,
),
);
}
}
This is my Stateful widget
bool isLightOn = false;
#override
Widget build(BuildContext context) {
return Container(
color: Colors.blue,
padding: new EdgeInsets.all(5.0),
child: Column(
children: <Widget>[
LightBulb(
isLightOn: isLightOn,
),
LightButton(
isLightOn: isLightOn,
onButtonPress: onButtonPress,
),
LightColorSelector(),
],
),
);
}
void onButtonPress() {
if (isLightOn == false) {
setState(() {
isLightOn = true;
});
} else {
setState(() {
isLightOn = false;
});
}
}
}
How can I handle these problems and how can I manipulate DropdownButton values?
Likewise, I want to reflect that DropdownButton value with changing LightBulb's container color.
Here is LightBulb class
final bool isLightOn;
LightBulb({this.isLightOn});
#override
Widget build(BuildContext context) {
return Container(
color: isLightOn == false ? Colors.red : Colors.green,
padding: EdgeInsets.all(5.0),
child: isLightOn == false ? Text("OFF") : Text("ON"),
);
}
}
Here is a full working example:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<String> dropdownValues = ['red', 'green', 'blue'];
String selected;
Color color;
#override
Widget build(BuildContext context) {
return Material(
child: Column(children: <Widget>[
DropdownButton<String>(
items: dropdownValues
.map((value) => DropdownMenuItem(
child: Text(value),
value: value,
))
.toList(),
onChanged: (String newValue) {
setState(() {
selected = newValue;
if (newValue == "red") color = Colors.red;
if (newValue == "green") color = Colors.green;
if (newValue == "blue") color = Colors.blue;
});
},
//isExpanded: false,
hint: Text('Chose Color'),
//selectedItemBuilder: ,
),
Container(
color: color != null ? color : Colors.black,
padding: EdgeInsets.all(5.0),
child: selected != null ? Text(selected) : Text("OFF", style: TextStyle(color: Colors.white)),
)
]),
);
}
}