Didn't change the color of container - flutter

I want to change the color of the Container when it is pressed and go to the new screen but when I come back the color must have changed.
class FreelancerLayout extends StatefulWidget {
const FreelancerLayout({Key? key}) : super(key: key);
#override
State<FreelancerLayout> createState() => _FreelancerLayoutState();
}
class _FreelancerLayoutState extends State<FreelancerLayout>
with AutomaticKeepAliveClientMixin<FreelancerLayout> {
#override
Widget build(BuildContext context) {
super.build(context);
return SingleChildScrollView(
physics: const BouncingScrollPhysics(),
child: Column(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 15.0),
child: GridView.builder(
itemCount: catList.length,
shrinkWrap: true,
primary: false,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 8.0,
mainAxisSpacing: 10.0),
itemBuilder: (context, index) => Center(
child: GridCategory(
category: catList[index],
press: () {
pushNewScreen(context,
screen: CategoryPage(category: catList[index]));
}),
),
),
),
GridCategory.dart
class GridCategory extends StatefulWidget {
final Category category;
final VoidCallback? press;
const GridCategory({
Key? key,
required this.category,
this.press,
// required this.selectedIcon,
// required this.unSelectedIcon,
}) : super(key: key);
#override
State<GridCategory> createState() => _GridCategoryState();
}
class _GridCategoryState extends State<GridCategory> {
final bool isSelected = false;
#override
Widget build(BuildContext context) {
return InkWell(
onTap: widget.press,
child: Container(
width: 110,
decoration: BoxDecoration(
color: isSelected ? AppColors.fIconsAndTextColor : Colors.white,
borderRadius: BorderRadius.circular(30.0)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(child: Image.asset(widget.category.catImage!)),
Text(
widget.category.iconName!,
textAlign: TextAlign.center,
style: TextStyle(color: isSelected ? Colors.white : Colors.black),
),
const SizedBox(height: 10)
],
),
),
);
}
}

First, I don't see any method to change isSelected here, soo it value alway false. Second, isSelected is final make it value can't changes, remove final. Thirt, because isSelected is local props, it changes will no appear in other page, you need to passing selected from parent if you want it.
Update: In case you want highlight selected category when selected and change it when select other cate? You need create a variable call 'selectedIndex' to store the selected category index, handle changes it everytime u tap a category. Update code below
_FreelancerLayoutState
...
int? selectedIndex; // Add this
#override
Widget build(BuildContext context) {
...
itemBuilder: (context, index) => Center(
child: GestureDetector(
onPressed: () {
setState(() => selectedIndex = index);
pushNewScreen(
context,
screen: CategoryPage(category: catList[index])
);
},
child: GridCategory(
category: catList[index],
isSelected: selectedIndex == index,
),
),
),
...
}
}
GridCategory
class GridCategory extends StatefulWidget {
...
final Category category;
final bool isSelected; // add this
// final VoidCallback? press; Remove this
...
}
_GridCategoryState
...
// final bool isSelected = false; Remove this
...
#override
Widget build(BuildContext context) {
// Removed InkWell
// return InkWell(
// onTap: widget.press,
// child: ...
// );
return Container(
width: 110,
decoration: BoxDecoration(
color: widget.isSelected ? AppColors.fIconsAndTextColor : Colors.white,
borderRadius: BorderRadius.circular(30.0)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(child: Image.asset(widget.category.catImage!)),
Text(
widget.category.iconName!,
textAlign: TextAlign.center,
style: TextStyle(color: widget.isSelected ? Colors.white : Colors.black),
),
const SizedBox(height: 10)
],
),
),
}
...

Change the GridCategory widget to a stateful widget. Then you can update the onTap function to change the boolean and then call the callback.
onTap: (){
setState((){
isSelected = true;
});
press();
},

On your GridCategory widget, pass isSelected from parent.
class GridCategory extends StatelessWidget {
final Category category;
final VoidCallback? press;
final bool isSelected;
const GridCategory({
Key? key,
required this.isSelected,
required this.category,
this.press,
}) : super(key: key);
......
To keep track of selected index you need a list, I am using List<int> here,
class _FreelancerLayoutState extends State<FreelancerLayout>
with AutomaticKeepAliveClientMixin<FreelancerLayout> {
List<int> selectedIndex = [];
....
itemBuilder: (context, index) => Center(
child: GridCategory(
isSelected: selectedIndex.contains(index),
press: () {
if (selectedIndex.contains(index)) {
selectedIndex.remove(
index); // remove selected index if already exist
} else {
selectedIndex.add(index);
}
//... perform others
}),

Related

I need selectable buttoon in flutter

what i get_____whai i wantbut when i use ToggleButttons i cant change its shape(i need rounded), and cant put more distance beetwen buttons. Toggle button is list in which put icons. But how i can make selectabe(only one of thr buuton) without toggle like in exaple or with toglleButoon
class MyToggleButtonsState extends State<MyToggleButtons> {
List<bool> iSselected = List.generate(4,(index)=> false);
List<IconData> icon = [MyFlutterApp.mobile,Icons.computer,Icons.monitor_heart,Icons.collections_bookmark_sharp ];
#override
Widget build(BuildContext context) {
return ToggleButtons(
selectedColor: Colors.white,
renderBorder: false,
isSelected: iSselected,
fillColor: Colors.orange,
onPressed: (int newIndex) {
setState(() {
for(int index = 0; index < iSselected.length; index++){
if(index == newIndex){
iSselected[index] = true;
} else{
iSselected[index] = false;
}
}
});
},
children: [
CustomIcon(
radius: BorderRadius.circular(32.0),
isSelected: iSselected[0],
icon: const Icon(MyFlutterApp.mobile),
),
CustomIcon(
radius: BorderRadius.circular(32.0),
isSelected: iSselected[1],
icon: const Icon(Icons.computer)
),
CustomIcon(
radius: BorderRadius.circular(32.0),
isSelected: iSselected[2],
icon: const Icon(Icons.monitor_heart)
),
CustomIcon(
radius: BorderRadius.circular(32.0),
isSelected: iSselected[3],
icon: const Icon(Icons.collections_bookmark_sharp)
)
]
);[What i want][1][What i can][1]
}
}
Thank you very much
You can achieve this by doing the following!
class CustomPageWithToggle extends StatefulWidget {
const CustomPageWithToggle({Key? key}) : super(key: key);
#override
State<CustomPageWithToggle> createState() => _CustomPageWithToggleState();
}
class _CustomPageWithToggleState extends State<CustomPageWithToggle> {
List<bool> isSelected = List.generate(5, (index) => false);
List<IconData> icons = [Icons.phone_android, Icons.computer, Icons.monitor_heart, Icons.menu_book, Icons.fastfood];
List<String> texts = ['Phones', 'Computers', 'Health', 'Books', 'Food'];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Example'),
),
backgroundColor: const Color.fromARGB(255, 218, 218, 218),
body: Column(
children: [
const SizedBox(
height: 10,
),
CustomToggle(
icons: icons,
texts: texts,
setStateFunction: setState,
isSelected: isSelected,
),
// Put Your Content Here
],
),
);
}
}
class CustomToggle extends StatelessWidget {
final List<IconData> icons;
final List<String> texts;
final Function setStateFunction;
final List<bool> isSelected;
const CustomToggle({
Key? key,
required this.icons,
required this.texts,
required this.setStateFunction,
required this.isSelected,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
// You should use this widget: SingleChildScrollView if your ToggleButtons are too long and overflow the screen.
// This makes it scrollable. If yours will not overflow, you can remove this widget.
scrollDirection: Axis.horizontal,
child: ToggleButtons(
isSelected: isSelected,
onPressed: (index) {
setStateFunction(() {
for (int i = 0; i < isSelected.length; i++) {
if (i == index) {
isSelected[i] = true;
} else {
isSelected[i] = false;
}
}
});
},
renderBorder: false,
fillColor: Colors.transparent,
splashColor: Colors.orange,
// Include other design properties if needed.
children: List<Widget>.generate(icons.length, (index) {
return CustomButton(
text: texts[index],
icondata: icons[index],
isSelected: isSelected[index],
);
}),
),
);
}
}
class CustomButton extends StatelessWidget {
final String text;
final IconData icondata;
final bool isSelected;
const CustomButton({
Key? key,
required this.text,
required this.icondata,
this.isSelected = false,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Column(
children: [
Container(
width: 70,
height: 70,
margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration: BoxDecoration(
color: isSelected ? Colors.orange : Colors.white,
shape: BoxShape.circle,
),
child: Icon(
icondata,
color: isSelected ? Colors.white : Colors.grey,
),
),
const SizedBox(height: 10),
Text(
text,
style: TextStyle(
color: isSelected ? Colors.orange : Colors.grey,
),
),
],
);
}
}
Explanation:
Using the ToggleButtons widget is the right choice for this. But as you said, using the properties of ToggleButtons can't create the button design you want. Therefore you have to provide your own custom button to the ToggleButtons child propaties.
Also, one important change I made to your code is, your code has the state controlled in the MyToggleButtons. But, mine is controlled at the Parent Widget(CustomPageWithToggle) not the CustomToggle. Yours will also work for your Toggle button but, the widget outside(parent widget, etc) can't access the isSelected list (Which probably you may want to use outside the toggle button). Notice with my code that any widget inside CustomPageWithToggle can access the isSelected variable.
Result:
If you don't understand or have questions leave a comment and I'll answer!

How to call setsate function from a different widget?

Well, I am coding a chatbot-like page in my app. But, I am stuck at calling setState function for page inside of chatBubble widget. Here is my page as MedicBot and chat question code as FirstQuestion. What I do want to do that whenever, user triggers radio tile's on tap condition. It should be trigger setState function in MedicBot, any suggestions?
import 'package:medicte/assets/back_button.dart';
import 'package:medicte/assets/first_question.dart';
class MedicBot extends StatefulWidget {
const MedicBot({Key? key}) : super(key: key);
#override
State<MedicBot> createState() => _MedicBotState();
}
class _MedicBotState extends State<MedicBot> {
late final List<Widget> _messages;
late final List<dynamic> botMessages;
FocusNode _focusNode = FocusNode();
setMainState() {
print('bum');
this.setState(() {});
}
#override
void initState() {
print('bumbeyarag');
botMessages = [
_buildChatBubbles(
widget: SizedBox.shrink(),
text:
'Do you have further medical information you can share? (e.g. lab results)',
userControl: false),
_buildChatBubbles(
widget: FirstQuestion(
focus: _focusNode,
radioButtons: ['1-2 weeks', 'A Month', '1-3 Months', 'Other'],
setMainState: setMainState,
),
text: 'Where do you currently live?',
userControl: false),
_buildChatBubbles(
widget: FirstQuestion(
focus: _focusNode,
radioButtons: [
'Online Consultation',
'Second Opinion',
'A treatment cost',
'Other'
],
setMainState: setMainState,
),
text: 'How soon do you want to get the treatment done?',
userControl: false),
_buildChatBubbles(
widget: FirstQuestion(
focus: _focusNode,
radioButtons: ['Yes', 'No'],
setMainState: () {
setState(() {});
},
),
text: 'What service are you looking for?',
userControl: false),
_buildChatBubbles(
widget: FirstQuestion(
focus: _focusNode,
radioButtons: [],
setMainState: () {
setState(() {});
},
),
text: 'Have you already spoken a doctor?',
userControl: false),
_buildChatBubbles(
text: 'Which treatment are you interested in?',
userControl: false,
widget:
const Text('Enter a treatment name (e.g Hair Transplant, IVF)')),
_buildChatBubbles(
text: 'You are inquiring for',
userControl: false,
widget: FirstQuestion(
radioButtons: const ['Myself', 'For someone else'],
focus: _focusNode,
setMainState: () {
setState(() {});
},
)),
];
_messages = [
const SizedBox(
height: 1,
),
const SizedBox(
height: 10,
)
];
super.initState();
}
final TextEditingController _controller = TextEditingController();
bool value = false;
#override
Widget build(BuildContext context) {
if (botMessages.isNotEmpty) {
_messages.insert(1, botMessages.removeLast());
}
return Scaffold(
bottomSheet: Container(
color: Colors.white30,
child: Padding(
padding: const EdgeInsets.only(bottom: 30, right: 15, left: 15),
child: TextFormField(
focusNode: _focusNode,
controller: _controller,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(25),
),
hintText: 'Type your message',
suffixIcon: IconButton(
onPressed: () {
print(_controller.text);
print(_controller.value);
setState(() {
_messages.insert(
1,
_buildChatBubbles(
text: _controller.text,
userControl: true,
widget: const SizedBox.shrink()));
_controller.clear();
});
},
icon: const Icon(Icons.send),
),
),
),
),
),
appBar: AppBar(
leadingWidth: 101,
backgroundColor: Colors.blue.shade300,
leading: Row(
children: [
const BackWardButton(),
ClipRRect(
borderRadius: BorderRadius.circular(1000),
child: Container(
color: Colors.white,
child: Image.asset(
'lib/images/Lovepik_com-401792159-medical-robot.png',
height: 53,
width: 53),
),
),
],
),
title: const Text(
"MedicBot",
style: TextStyle(color: Colors.black54),
),
),
body: SafeArea(
minimum:
const EdgeInsets.only(top: 2, left: 10, right: 10, bottom: 90),
child: ListView.builder(
itemCount: _messages.length,
reverse: true,
itemBuilder: ((context, index) {
return _messages[index];
}),
)));
}
}
class _buildChatBubbles extends StatelessWidget {
bool userControl;
String text;
Widget widget;
_buildChatBubbles(
{required this.widget,
required this.text,
required this.userControl,
super.key});
#override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.only(bottom: 10),
child: Row(
mainAxisAlignment:
userControl ? MainAxisAlignment.end : MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
userControl
? const SizedBox.shrink()
: Container(
margin: const EdgeInsets.only(right: 10),
child: const CircleAvatar(
radius: 20,
backgroundImage: AssetImage(
'lib/images/Lovepik_com-401792159-medical-robot.png'),
),
),
Container(
constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.height * 0.4,
maxWidth: MediaQuery.of(context).size.width * 0.6),
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: userControl ? Colors.green.shade300 : Colors.blue.shade300,
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
spreadRadius: 1,
blurRadius: 7,
offset: const Offset(0, 3), // changes position of shadow
),
],
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
userControl ? 'You' : 'Medicte Bot',
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 5),
Flexible(
child: Text(
text,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w400,
),
),
),
widget
],
),
),
],
),
);
;
}
}
import 'package:flutter/material.dart';
import 'package:group_button/group_button.dart';
import 'package:medicte/pages/chat_ui.dart';
// ignore: must_be_immutable
class FirstQuestion extends StatefulWidget {
List<String> radioButtons;
FocusNode focus;
void Function() setMainState;
FirstQuestion(
{required this.setMainState,
required this.focus,
required this.radioButtons,
Key? key})
: super(key: key);
#override
State<FirstQuestion> createState() => _FirstQuestionState();
}
class _FirstQuestionState extends State<FirstQuestion> {
late GroupButtonController _radioController;
// ignore: prefer_typing_uninitialized_variables
late final _radioButtons;
#override
void initState() {
_radioButtons = widget.radioButtons;
_radioController = GroupButtonController(
selectedIndexes: [0, 1, 2, 3],
);
super.initState();
}
#override
Widget build(BuildContext context) {
return GroupButton(
controller: _radioController,
isRadio: true,
options: const GroupButtonOptions(groupingType: GroupingType.column),
buttons: _radioButtons,
buttonIndexedBuilder: (selected, index, context) {
return RadioTile(
title: _radioButtons[index],
selected: _radioController.selectedIndex,
index: index,
onTap: () {
print(_radioButtons[index].toString());
widget.setMainState();
_radioController.selectIndex(index);
/* Future.delayed(Duration(seconds: 1), () {
widget.setMainState();
}); */
},
);
},
onSelected: (val, i, selected) {
print('object');
});
}
}
class RadioTile extends StatelessWidget {
const RadioTile({
Key? key,
required this.selected,
required this.onTap,
required this.index,
required this.title,
}) : super(key: key);
final String title;
final int index;
final int? selected;
final VoidCallback onTap;
#override
Widget build(BuildContext context) {
return ListTile(
title: Text(title),
onTap: onTap,
leading: Radio<int>(
groupValue: selected,
value: index,
onChanged: (val) {
print(val);
onTap();
},
),
);
}
}
Try something like this. This is the code snippet of an application of mine. I used StatefulBuilder as the parent of the widgets I want to update and I sent the setState parameter to the widget where I trigger.
import 'package:flutter/material.dart';
class CryptoassetsPage extends StatefulWidget {
const CryptoassetsPage({Key? key}) : super(key: key);
#override
_CryptoassetsPageState createState() => _CryptoassetsPageState();
}
class _CryptoassetsPageState extends State<CryptoassetsPage> {
#override
Widget build(BuildContext context) {
return Container(
color: Theme.of(context).backgroundColor,
child: SingleChildScrollView(
child: StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
//My other class/widget
return OrderOptions(setState);
}),
),
);
}
}
class OrderOptions extends StatefulWidget {
const OrderOptions(this.setState, {Key? key}) : super(key: key);
final StateSetter setState;
#override
_OrderOptionsState createState() => _OrderOptionsState();
}
class _OrderOptionsState extends State<OrderOptions> {
#override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
StateSetter setState = widget.setState;
setState(() {});
},
);
}
}

The numbers in the counter do not change when clicking on the buttons in flutter

I have a counter with a price and buttons with price increment and decrement. I do it all through bloc, but I ran into an error that when I click on the buttons, my price does not change. Accordingly, the state does not change, as I understand it. What exactly is the reason and how can I fix the error so that the price changes when you click on the buttons?
price_counter
class PriceCounter extends StatelessWidget {
PriceCounter({Key? key, required this.price}) : super(key: key);
double price = 0.13;
#override
Widget build(BuildContext context) {
final FilterPriceCubit cubit = BlocProvider.of<FilterPriceCubit>(context);
return BlocBuilder<FilterPriceCubit, FilterPriceState>(
builder: (context, state) {
if (state is FilterPriceInitial) {
state.fitlerPrice = price;
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 21),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
onPressed: () =>
cubit.priceFilterDecrement(state.fitlerPrice),
icon: SvgPicture.asset(constants.Assets.minus),
constraints: const BoxConstraints(),
padding: EdgeInsets.zero,
),
const SizedBox(width: 20),
InputFieldPrice(
price: state.fitlerPrice,
textStyle: constants.Styles.normalBookTextStyleWhite),
const SizedBox(width: 20),
IconButton(
onPressed: () =>
cubit.priceFilterIncrement(state.fitlerPrice),
icon: SvgPicture.asset(constants.Assets.plus),
constraints: const BoxConstraints(),
padding: EdgeInsets.zero,
),
],
),
);
}
return const SizedBox();
},
);
}
}
input_fields_price
class InputFieldPrice extends StatefulWidget {
final double price;
final TextStyle textStyle;
const InputFieldPrice(
{Key? key, required this.price, required this.textStyle})
: super(key: key);
#override
State<InputFieldPrice> createState() => _InputFieldPrice();
}
class _InputFieldPrice extends State<InputFieldPrice> {
final _formKey = GlobalKey<FormState>();
final _priceController = TextEditingController();
#override
void dispose() {
_priceController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) => SizedBox(
width: 100,
child: Form(
key: _formKey,
child: TextFormField(
keyboardType: TextInputType.number,
controller: _priceController
..text = widget.price.toStringAsFixed(2),
style: widget.textStyle,
textAlign: TextAlign.center,
decoration: InputDecoration(
prefix: Text('JC', style: widget.textStyle),
suffix: const Text(
'KWh',
style: constants.Styles.smallerBookTextStyleWhite,
),
contentPadding: EdgeInsets.zero,
border: InputBorder.none,
),
inputFormatters: [
LengthLimitingTextInputFormatter(4),
FilteringTextInputFormatter.allow(RegExp("[0-9.]")),
],
),
),
);
}
Everytime the bloc builder is called the state.fitlerPrice is set to price. Please remove this from bloc builder. Rest everything seems to be good.
state.fitlerPrice = price;

How to pass data to textfield and return new changed data?

I faced the following problem. I have a database from which I get data through bloc - state.mapFilter.maxPrice. I want to transfer this data to the textfield where it will be displayed. In the textfield I have a counter which is also implemented via bloc with increment and decrement. How can I pass a value from state.mapFilter.maxPrice to a textfield so that this value can be changed and then returned back and updated in state.mapFilter.maxPrice ?
main - state.mapFilter.maxPrice is the data from the database that I want to show in the text field
PriceCounter(
price: state.mapFilter.maxPrice,
),
price_counter - this is the widget itself with a text field and buttons to increase/decrease the value
class PriceCounter extends StatelessWidget {
PriceCounter({Key? key, required this.price}) : super(key: key);
double price;
#override
Widget build(BuildContext context) {
final CounterCubit cubit = BlocProvider.of<CounterCubit>(context);
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 21),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
onPressed: () => cubit.priceFilterDecrement(),
icon: SvgPicture.asset(constants.Assets.minus),
constraints: const BoxConstraints(),
padding: EdgeInsets.zero,
),
const SizedBox(width: 20),
BlocBuilder<CounterCubit, CounterState>(
builder: (context, state) => InputFieldPrice(
price: state.priceFilterCountValue,
textStyle: constants.Styles.normalBookTextStyleWhite),
),
const SizedBox(width: 20),
IconButton(
onPressed: () => cubit.priceFilterIncrement(),
icon: SvgPicture.asset(constants.Assets.plus),
constraints: const BoxConstraints(),
padding: EdgeInsets.zero,
),
],
),
);
}
}
input_field_price - this is the text field
class InputFieldPrice extends StatefulWidget {
final double price;
final TextStyle textStyle;
final Function(double)? onChanged;
const InputFieldPrice(
{Key? key, required this.price, required this.textStyle, this.onChanged})
: super(key: key);
#override
State<InputFieldPrice> createState() => _InputFieldPrice();
}
class _InputFieldPrice extends State<InputFieldPrice> {
final _formKey = GlobalKey<FormState>();
final _priceController = TextEditingController();
#override
void dispose() {
_priceController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return SizedBox(
width: 100,
child: Form(
key: _formKey,
child: TextFormField(
keyboardType: TextInputType.number,
controller: _priceController..text = widget.price.toStringAsFixed(2),
style: widget.textStyle,
textAlign: TextAlign.center,
decoration: InputDecoration(
prefix: Text('JC', style: widget.textStyle),
suffix: const Text(
'KWh',
style: constants.Styles.smallerBookTextStyleWhite,
),
contentPadding: EdgeInsets.zero,
border: InputBorder.none,
),
// onChanged: (value) {
// cubit.setPrice(value);
// double price = double.parse(value);
// widget.onChanged!(price);
// },
),
),
);
}
}
You could set data in textfield with TextEditingController.text = <your data>
and the reverse to set data to variable; <var / getx> = TextEditingController.text

Function callback to change text color (just for one) | Flutter

I'm trying to create a SideMenu with different SideMenuItems.
For that I created a new class and want to update the color of Text when the SideMenuItem is clicked. For that I want to transfer the activeState and all that stuff you see in the code below:
The use of my class in the Widget:
bool isActive = false;
...
SideMenuItem(
icon: Icon(
Icons.inbox,
size: 20,
color: isActive ? kPrimaryColor : kGrayColor,
),
activeState: isActive,
title: "Archiv",
toggleActiveState: (activeState) {
setState(() {
isActive = !activeState;
});
},
),
And here is my class:
import 'package:flutter/material.dart';
import 'package:gastronomy/constants.dart';
class SideMenuItem extends StatelessWidget {
// ignore: prefer_const_constructors_in_immutables
SideMenuItem({
Key? key,
required this.activeState,
this.itemCount = 0,
this.showBorder = true,
#required this.icon,
#required this.title,
required this.toggleActiveState,
}) : super(key: key);
final bool activeState;
final bool showBorder;
final int itemCount;
final Icon? icon;
final String? title;
final Function(bool) toggleActiveState;
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(top: kDefaultPadding),
child: InkWell(
onTap: () {
toggleActiveState(activeState);
},
child: Row(
children: [
const SizedBox(width: 15),
const SizedBox(width: kDefaultPadding / 4),
Expanded(
child: Container(
padding: const EdgeInsets.only(bottom: 15, right: 5),
decoration: showBorder
? const BoxDecoration(
border: Border(
bottom: BorderSide(color: Color(0xFFDFE2EF)),
),
)
: null,
child: Row(
children: [
icon!,
const SizedBox(width: kDefaultPadding * 0.75),
Text(
title!,
style: Theme.of(context).textTheme.button?.copyWith(
color: activeState ? kTextColor : kGrayColor,
),
),
const Spacer(),
// if (itemCount != null) CounterBadge(count: itemCount)
],
),
),
),
],
),
),
);
}
}
I ended up with that pieces of code but well, how you might know, all SideMenuItems change there color when I click one.
I'm pretty new at using this way of code so I would be thankful to all informations you can include into your answer.
One option is to render all the menu items through a map function and compare each item with the selected option, like in the example below:
import 'package:flutter/material.dart';
class MenuExample extends StatefulWidget {
const MenuExample({Key? key}) : super(key: key);
#override
_MenuExampleState createState() => _MenuExampleState();
}
class _MenuExampleState extends State<MenuExample> {
List<String> menuOptions = const ['Item 1', 'Item 2', 'Item 3'];
String selectedOption = '';
#override
Widget build(BuildContext context) {
return Scaffold(
drawer: Drawer(
backgroundColor: Colors.amber,
child: ListView(
children: menuOptions.map((menuOption) {
return InkWell(
onTap: () => setState(() {
selectedOption = menuOption;
}),
child: MenuItem(
name: menuOption,
isSelected: menuOption == selectedOption,
),
);
}).toList()),
),
);
}
}
class MenuItem extends StatelessWidget {
const MenuItem({Key? key, this.isSelected = false, required this.name})
: super(key: key);
final bool isSelected;
final String name;
#override
Widget build(BuildContext context) {
return ListTile(
title: Text(
name,
style: TextStyle(
fontWeight: isSelected ? FontWeight.bold : FontWeight.normal),
),
);
}
}