flutter listview skroll resets counter in text widget - flutter

I had this test app part working. it would update bagel counter but would update all the bagel counter on screen. I moved my cubit build.provider to just the text field displaying count per item on screen.
This fix my global update to all bagel counts. so each now maintains own counter. but now when i scroll off the screen, the counts are all reset. I pull in the + 0 1 counter into listview as a class onto itself.
I have tried adding keys and
addAutomaticKeepAlives: true but no luck. fixing delete off scroll of counter 0 between + - being reset..
main.dart
//TODO Screen Layouts
//TODO json pull and post
//TODO where to send post to email sms for store to see
//TODO Update live db with fields add to test dp retailp and mobileactive
//TODO Create batch process to generate json file from db nightly or on demain via a button
//TODO TEST code
//TODO spining on load bagel icon or sprit - make.
//TODO total bagels / breads order
//TODO shopping card added
//TODO snackbar menu for as total add up pop up totals
import 'package:flutter/material.dart';
import 'Services.dart';
import 'Product.dart';
import 'bagelcounter.dart';
import 'cubit/counter_state.dart';
import 'cubit/counter_cubit.dart';
import 'cubit/counter_cubit_page.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; //addded
void main() => runApp(MyApp());
// #docregion MyApp
class MyApp extends StatelessWidget {
final bool keepAlive = true; // not working
// #docregion build
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Startup Name Generator',
theme: ThemeData(
// Add the 3 lines from here...
primarySwatch: Colors.blue,
textTheme: TextTheme(
headline1: TextStyle(
fontFamily: 'Corben',
fontWeight: FontWeight.w700,
fontSize: 24,
color: Colors.black,
),
),
), // ... to here.
home: buildJsonParseDemo(),
// org home: buildJsonParseDemo(),
);
}
JsonParseDemo buildJsonParseDemo() => JsonParseDemo();
// #enddocregion build
}
class JsonParseDemo extends StatefulWidget {
//
JsonParseDemo() : super();
#override
_JsonParseDemoState createState() => _JsonParseDemoState();
}
class _JsonParseDemoState extends State<JsonParseDemo> {
//
List<Product> _product;
bool _loading;
//quick fix make this getter
//static //todo make live counter
int mbakerdoz = 0;
//get bakerdoz => mbakerdoz;
//static //todo make live counter
int singles = 10;
#override
void initState() {
super.initState();
_loading = true;
Services.getUsers().then((product) {
setState(() {
_product = product;
_loading = false;
});
});
}
//TODO find day of week to only see items available on day:
//DateTime date = DateTime.now();
//print("weekday is ${date.weekday}");
//TODO Add quantiy field of 1 - 6 , default 0 ,to bagel and breads
//TODO Bottom total of item and price. Tax not included
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(_loading ? 'Loading...' : 'Bagels & Breads'),
),
body: Container(
color: Colors.white,
child: ListView.separated(
key: UniqueKey(),
addAutomaticKeepAlives: true, //not working to sotp skroll delete
// key: UniqueKey(), key not fix update all.
separatorBuilder: (context, index) => Divider(
color: Colors.black,
thickness: 2,
),
itemCount: null == _product ? 0 : _product.length,
itemBuilder: (context, index) {
Product product = _product[index];
return ListTile(
key: UniqueKey(),
isThreeLine: true,
// leading: Icon(Icons.plus_one),
// trailing: Icon(Icons.exposure_minus_1),
title: Text(product.pname,
style: TextStyle(
color: Colors.blue[900],
fontSize: 22.0,
fontWeight: FontWeight.w500)),
// product name
subtitle: Text(
'\$ ' +
(product.retailp.toStringAsFixed(2) +
' each index:' +
'$index ' +
' qty ' +
product.qty.toString()),
key: UniqueKey(),
style: TextStyle(
color: Colors.black,
fontSize: 18.0,
fontWeight: FontWeight.w400)
),
trailing: SizedBox(
key: UniqueKey(),
width: 150,
child: BlocProvider<CounterCubit>(
key: UniqueKey(),
create: (context) => CounterCubit(),
child: CounterCubitPage(),
)),
);
},
),
),
bottomNavigationBar: BottomAppBar(
child: Row(
children: [
//IconButton(icon: Icon(Icons.menu), onPressed: () {}),
Spacer(),
Container(
height: 55.0,
width: 1.0,
),
//TODO get bakerdoz and etotal on footer working need to pass data between main and bagelcounter
Text("Baker's Dozen: $mbakerdoz " + " Singles: $singles",
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
fontWeight: FontWeight.w500)),
Spacer(),
//IconButton(icon: Icon(Icons.search), onPressed: () {}),
//IconButton(icon: Icon(Icons.more_vert), onPressed: () {}),
],
),
shape: CircularNotchedRectangle(),
color: Colors.lightBlue,
notchMargin: 8.0,
),
//floatingActionButton:
// FloatingActionButton(child: Icon(Icons.add), onPressed: () {}),
//floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
);
}
}
counter_cubit_page.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'counter_cubit.dart';
import 'counter_state.dart';
class CounterCubitPage extends StatelessWidget {
// static const String routeName = '/counter_cubit';
//#override
// bool get wantKeepAlive => true; // not work
// final bool keepAlive = true; // try to keep counter on skroll????
#override
Widget build(BuildContext context) => Scaffold(
key: UniqueKey(),
//appBar: AppBar(title: const Text('Counter Cubit Bloc Double CTest')),
body: BlocBuilder<CounterCubit, CounterCubitState>(
key: UniqueKey(),
builder: (context, state) => Column(
children: [
Row(
key: UniqueKey(),
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
icon: Icon(Icons.add_circle),
color: Colors.blue,
iconSize: 25,
onPressed: () => context.read<CounterCubit>().increment(),
),
Text(
'${state.totalbagels}',
key: GlobalKey(), // not working
style: Theme.of(context).textTheme.headline4,
),
IconButton(
icon: Icon(Icons.remove_circle),
color: Colors.blue,
iconSize: 25,
onPressed: () => context.read<CounterCubit>().decrement(),
),
],
),
],
),
),
);
}
I had tried addAutomaticKeepAlives: true not working and try unique keys on fields ...
any pointers welcome. I am new to flutter coding .. still lots to learn..
enter image description here

Related

Only one List item displayed when changing screen / page

On the add Weight screen I pick a weight and a date and then it gets stored in a list in the Hive database, once I press "Save".
It also returns me to the Homepage, where I would like to depict the stored list items in a ListView.Builder.
I only get the last item on the list and not the whole list.
When I am at the add weight screen, I see that there are more items in the list, but once I return to homepage only the last one exists.
AddWeightScreen
import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/container.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:intl/intl.dart';
import 'package:weighty/components/my_alert_box.dart';
import 'package:weighty/data/database.dart';
import 'package:weighty/screens/home_page.dart';
class AddWeight extends StatefulWidget {
const AddWeight({super.key});
#override
State<AddWeight> createState() => _AddWeightState();
}
class _AddWeightState extends State<AddWeight> {
Database db = Database();
final _myBox = Hive.box("mybox");
double _currentValue = 0;
DateTime _dateTime = DateTime.now();
String formattedDate = DateFormat('d MMM yyyy').format(DateTime.now());
final _weightController = TextEditingController();
void _showDatePicker() {
showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2000),
lastDate: DateTime.now(),
).then((value) {
setState(() {
_dateTime = value!;
formattedDate = DateFormat('d MMM yyyy').format(_dateTime);
});
});
}
// add weight from text - keyboard
void _dialogNumber() {
showDialog(
context: context,
builder: (context) {
return MyAlertBox(
controller: _weightController,
hintText: "Enter today's weight...",
onSave: () {
if (double.parse(_weightController.text) > 200) {
_weightController.text = "200";
}
setState(() {
_currentValue = double.parse(_weightController.text);
});
_weightController.clear();
Navigator.pop(context);
},
onCancel: cancelDialogBox);
});
}
//save method
void _saveWeightAndDate() {
setState(() {
db.weightList.add([_currentValue, formattedDate]);
});
db.saveData();
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const HomePage(),
),
);
}
// cancel new weight input
void cancelDialogBox() {
// clear textfield
_weightController.clear();
// pop dialog box
Navigator.of(context).pop();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xFFD9F0FF),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
children: [
const SizedBox(
height: 28.0,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
"Add Weight",
style: TextStyle(fontSize: 36, fontWeight: FontWeight.w600),
),
MaterialButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text(
'CANCEL',
style: TextStyle(
color: Color(0xff878472),
fontSize: 16.0,
fontWeight: FontWeight.bold,
),
),
),
],
),
const SizedBox(height: 30),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Expanded(
child: MaterialButton(
onPressed: _dialogNumber,
child: Text(
_currentValue.toStringAsFixed(2) + " kg",
style: TextStyle(
color: Color(0xFF006B8F),
fontSize: 46,
fontWeight: FontWeight.w500),
),
),
),
const SizedBox(height: 30),
Slider(
value: _currentValue,
min: 0,
max: 200,
onChanged: ((value) {
setState(() {
_currentValue = value;
});
}),
),
const SizedBox(height: 30),
TextButton.icon(
onPressed: _showDatePicker,
icon: const Icon(
Icons.date_range_outlined,
size: 24.0,
color: Color(0xff878472),
),
label: Text(
formattedDate,
style: TextStyle(color: Color(0xff878472), fontSize: 18),
),
),
const SizedBox(height: 30),
ElevatedButton(
onPressed: _saveWeightAndDate,
child: Text(
'SAVE',
style:
TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
style: ElevatedButton.styleFrom(
elevation: 24,
padding:
EdgeInsets.symmetric(vertical: 20, horizontal: 80),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
side: BorderSide(color: Colors.white, width: 2),
),
),
),
const SizedBox(height: 30),
],
),
),
],
),
),
);
}
}
HomePage
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:weighty/components/weight_tile.dart';
import 'package:weighty/data/database.dart';
import 'package:weighty/main.dart';
import 'package:weighty/screens/add_weight.dart';
class HomePage extends StatefulWidget {
const HomePage({super.key});
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
void initState() {
//First time ever opening app, Create default data
// if (_myBox.get("WEIGHTLIST") == null) {
// }
//already exists data
db.loadData();
// db.saveData();
super.initState();
}
Database db = Database();
final _myBox = Hive.box("mybox");
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[100],
floatingActionButton: FloatingActionButton(
backgroundColor: Color(0xff006B8F),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const AddWeight(),
),
);
},
child: const Icon(Icons.add),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 28),
Text(
"CURRENT",
style: TextStyle(
color: Colors.grey[500],
fontSize: 16.0,
fontWeight: FontWeight.bold,
),
),
Text(
db.weightList.length == 0
? "00.0 Kg"
: db.weightList.last[0].toStringAsFixed(2) + " kg",
style: TextStyle(
color: Color(0xFF006B8F),
fontSize: 46.0,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 40),
Center(
child: Text(
"GRAPH",
style: TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.bold,
),
),
),
Expanded(
child: ListView.builder(
itemCount: db.weightList.length,
itemBuilder: (context, index) {
return WeightTile(
date: db.weightList[index][1],
weight: db.weightList[index][0].toStringAsFixed(2),
);
},
),
),
ElevatedButton(
onPressed: () {
print(db.weightList.length);
},
child: Text('Print!')),
],
),
),
);
}
}
Hive Database
import 'package:hive_flutter/hive_flutter.dart';
class Database {
//reference the box
final _myBox = Hive.box("mybox");
// Empty Weight List
List weightList = [];
// void createInitialData() {
// weightList = [];
// }
//load the date from the db
void loadData() {
weightList = _myBox.get("WEIGHTLIST");
}
//save the weight
void saveData() {
_myBox.put("WEIGHTLIST", weightList);
}
}
I could not rebuild your project to debug it. so I'm kind of taking a shot in the darkness.
there is a widget called valuelistenablebuilder which gets rebuilt when ever a value changes you can set your box to the value being listened by this widget and rebuild every time a new value is added to your box you can find an example on this page
For whole list you have to first get old list which is saved in hive then sum this list and save in to hive
Output is
For you example you have to update saveData method in to a Database class
void saveData() {
final myBox = Hive.box("mybox");
List? hiveList = [];
hiveList = myBox.get("WEIGHTLIST") ?? [];
if (hiveList!.isNotEmpty) {
hiveList += weightList;
} else {
hiveList = weightList;
}
_myBox.put("WEIGHTLIST", hiveList);
}
You will be get whole list into a homescreen

When I tab on Icon, its color changes only for seconds and disappears in Futter

So I have problem with the changing color of an icon when it tabbed
thus, when I tab on icon it's only changes for its prober colors but for seconds and then disappears
I have used Provider as shown in the below code, and I also used isChecked = true but when I tab on one icon, all of them change as well.
So what should I do with this problem?
this this the code but my problem remains in Icon Button which's will be below it
import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/container.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:note/Designs/Favorite_List.dart';
import 'package:note/Models/Favorite_List_Provider.dart';
import 'package:note/Models/Food_Models.dart';
import 'package:provider/provider.dart';
import '../Services/Fetch_Data.dart';
import 'Details_DesignOfDesignOne.dart';
class DesignOne extends StatefulWidget {
const DesignOne({super.key, required this.Image, required this.Desc});
final String Image;
final String Desc;
#override
State<DesignOne> createState() => _DesignOneState();
}
class _DesignOneState extends State<DesignOne> {
late Future<Food> futureFood;
#override
void initState() {
super.initState();
futureFood = fetchData(widget.Image, widget.Desc);
}
bool ischecked = false;
#override
Widget build(BuildContext context) {
final provider = favorite.of(context);
return Scaffold(
backgroundColor: Colors.grey.shade200,
appBar: AppBar(
title: Text('Design one'),
actions: [
Padding(
padding: const EdgeInsets.all(8.0),
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => FavoriteScreen(Desc: '', Image: ''),
),
);
},
child: Icon(
Icons.list,
size: 30,
),
),
)
],
),
body: Consumer<favorite>(
builder: (BuildContext context, favorite value, child) {
return Center(
child: FutureBuilder<Food>(
future: fetchData(widget.Image, widget.Desc),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data!.categories.length,
itemBuilder: (contxt, index) {
final fav = snapshot.data!.categories[index];
return InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailsDo(
Desc: snapshot.data!.categories[index]
.strCategoryDescription,
Image: snapshot
.data!.categories[index].strCategoryThumb,
),
),
);
},
child: Card(
elevation: 2,
shape: RoundedRectangleBorder(
side: BorderSide(color: Colors.white70, width: 1),
borderRadius: BorderRadius.circular(50),
),
child: ListTile(
title: Text(
snapshot.data!.categories[index].strCategory
.toString(),
style: GoogleFonts.montserrat(
fontSize: 20,
fontWeight: FontWeight.w600,
fontStyle: FontStyle.italic,
),
),
leading: CircleAvatar(
backgroundColor:
Color.fromARGB(213, 255, 251, 251),
child: Text(
snapshot.data!.categories[index].idCategory
.toString(),
style: GoogleFonts.montserrat(
fontSize: 20,
fontWeight: FontWeight.w600,
fontStyle: FontStyle.italic,
color: Color.fromARGB(255, 148, 148, 135)),
),
),
trailing: IconButton(
icon: (provider.isExist(fav) && ischecked)
? const Icon(Icons.favorite,
color: Colors.red)
: const Icon(Icons.favorite_border),
onPressed: () {
provider.toggleFavorite(fav);
setState(() {
ischecked = !ischecked;
});
},
),
),
),
);
});
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
return const CircularProgressIndicator();
},
),
);
}),
);
}
}
and this is the specific problem with the Icon Button :
trailing: IconButton(
icon: (provider.isExist(fav) && ischecked)
? const Icon(Icons.favorite,
color: Colors.red)
: const Icon(Icons.favorite_border),
onPressed: () {
provider.toggleFavorite(fav);
setState(() {
ischecked = !ischecked;
});
},
),
And here is the problem :
Would you try this way instead of isChecked variable??
class _DesignOneState extends State<DesignOne>{
static late List<bool> isChecked;
///*** your code ****
Widgetbuild(BuildContext context){
///*** your code ***
if(snapshot.hasData){
isChecked = List.filled(snapshot.data!.categories.length,false);
/// *** your code ***
icon: (provider.isExist(fav) && isChecked[index])
/// *** your code ***
setState((){
isChecked[index] = !isChecked[index];
});
}
}
}

How to change Elevated button's title and color onpressed

I'm developing an app to make meal reservations, and I have an ElevatedButton that opens an alert when pressed. This alert is where the user is able to confirm the reservation. So, the alert has 2 text buttons, and I need that when the "sim" button is pressed, the ElevatedButton changes from "Reservar" with green color to "Cancelar Reserva" with red color.
I tried this way but it doesn't work:
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import '../components/meal_item.dart';
import '../models/day_of_week.dart';
import '../models/want_to_comment.dart';
import '../models/meal.dart';
import '../utils/app_routes.dart';
import '../data/dummy_data.dart';
enum StatusReserva { y, n }
Color statusToColor(StatusReserva value) {
Color color = Colors.green;
switch (value) {
case StatusReserva.n:
break;
case StatusReserva.y:
color = Colors.red;
break;
}
return color;
}
String statusToString(StatusReserva value) {
String title = 'Reservar';
switch (value) {
case StatusReserva.n:
break;
case StatusReserva.y:
title = 'Cancelar Reserva';
break;
}
return title;
}
class DaysOfWeekMealsScreen extends StatefulWidget {
final List<Meal> meals;
final StatusReserva status;
final Function(StatusReserva) onStatusChanged;
const DaysOfWeekMealsScreen({
Key? key,
required this.meals,
required this.status,
required this.onStatusChanged,
}) : super(key: key);
#override
State<DaysOfWeekMealsScreen> createState() => _DaysOfWeekMealsScreenState();
}
class _DaysOfWeekMealsScreenState extends State<DaysOfWeekMealsScreen> {
StatusReserva status = StatusReserva();
#override
void initState() {
super.initState();
status = widget.status;
}
#override
Widget build(BuildContext context) {
final dayOfWeek = ModalRoute.of(context)!.settings.arguments as DayOfWeek;
final dayOfWeekMeals = widget.meals.where((meal) {
return meal.days_of_week.contains(dayOfWeek.id);
}).toList();
void _incrementCount(BuildContext context) {
dayOfWeek.count++;
}
Future<void> _showMyDialog(BuildContext context) async {
return showDialog<void>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: const Text(
' ',
),
content: SingleChildScrollView(
child: ListBody(
children: const <Widget>[
Text(
'Confirmar reserva para o dia XX/XX/XX?',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 15,
fontFamily: 'Raleway',
fontWeight: FontWeight.bold),
),
],
),
),
actions: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(
child: const Text('Sim'),
onPressed: () => {
_incrementCount,
Navigator.pop(context),
status = StatusReserva.y
},
),
TextButton(
child: const Text('Não'),
onPressed: () => Navigator.pop(context),
),
],
),
],
);
},
);
}
return Scaffold(
appBar: AppBar(
title: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Image.asset(
'assets/images/logo.png',
fit: BoxFit.contain,
height: 32,
),
Container(
padding: const EdgeInsets.all(8.0),
child: Text(dayOfWeek.title)),
],
),
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
),
margin: const EdgeInsets.all(10),
child: ElevatedButton(
onPressed: () => {_showMyDialog(context)},
style: ButtonStyle(
shape: MaterialStateProperty.all(RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
)),
padding: MaterialStateProperty.all(const EdgeInsets.all(15)),
backgroundColor:
MaterialStateProperty.all(statusToColor(widget.status)),
),
child: Text(statusToString(widget.status)),
),
),
Expanded(
child: ListView.builder(
itemCount: dayOfWeekMeals.length,
itemBuilder: (ctx, index) {
return MealItem(dayOfWeekMeals[index]);
},
),
),
],
),
);
}
}
import 'package:apetit_project/models/want_to_comment.dart';
import 'package:apetit_project/screens/login_screen.dart';
import 'package:flutter/material.dart';
import 'screens/tabs_screen.dart';
import 'screens/days_of_week_meals_screen.dart';
import 'screens/meal_detail_screen.dart';
import 'screens/settings_screen.dart';
import 'screens/want_to_comment_screen.dart';
import 'screens/comment_screen.dart';
import 'utils/app_routes.dart';
import 'models/meal.dart';
import 'models/settings.dart';
import 'data/dummy_data.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Settings settings = Settings();
StatusReserva status = StatusReserva();
List<Meal> _gourmetMeals = [];
List<Meal> _lightMeals = [];
void _filterMeals(Settings settings) {
setState(() {
this.settings = settings;
});
}
void _reserveMeals(StatusReserva status) {
setState(() {
this.status = status;
});
}
void _toggleGourmet(Meal meal) {
setState(() {
_gourmetMeals.contains(meal)
? _gourmetMeals.remove(meal)
: _gourmetMeals.add(meal);
});
}
bool _isGourmet(Meal meal) {
return _gourmetMeals.contains(meal);
}
void _toggleLight(Meal meal) {
setState(() {
_lightMeals.contains(meal)
? _lightMeals.remove(meal)
: _lightMeals.add(meal);
});
}
bool _isLight(Meal meal) {
return _lightMeals.contains(meal);
}
#override
Widget build(BuildContext context) {
final ThemeData tema = ThemeData(
fontFamily: 'Raleway',
textTheme: ThemeData.light().textTheme.copyWith(
headline6: const TextStyle(
fontSize: 20,
fontFamily: 'Raleway',
fontWeight: FontWeight.bold,
),
),
);
return MaterialApp(
title: 'Appetit',
theme: tema.copyWith(
colorScheme: tema.colorScheme.copyWith(
primary: const Color.fromRGBO(222, 1, 59, 1),
secondary: const Color.fromRGBO(240, 222, 77, 1),
),
),
routes: {
AppRoutes.LOGIN: (ctx) => LoginScreen(),
AppRoutes.HOME: (ctx) => TabsScreen(_gourmetMeals, _lightMeals),
AppRoutes.WANT_TO_COMMENT: (ctx) => const WantToCommentScreen(),
AppRoutes.COMMENT: (ctx) => const CommentScreen(),
AppRoutes.DAYS_OF_WEEK_MEALS: (ctx) => DaysOfWeekMealsScreen(
meals: DUMMY_MEALS,
status,
_reserveMeals,
),
AppRoutes.MEAL_DETAIL: (ctx) => MealDetailScreen(
_toggleGourmet, _isGourmet, _toggleLight, _isLight),
AppRoutes.SETTINGS: (ctx) => SettingsScreen(settings, _filterMeals),
},
);
}
createMaterialColor(Color color) {}
}
To change the state of a widget you can use setState
enum StatusReserva { y, n }
Color statusToColor(StatusReserva value) {
Color color = Colors.green;
switch (value) {
case StatusReserva.n:
break;
case StatusReserva.y:
color = Colors.red;
break;
}
return color;
}
class StatusTest extends StatefulWidget {
const StatusTest({Key? key}) : super(key: key);
#override
State<StatusTest> createState() => _StatusTestState();
}
class _StatusTestState extends State<StatusTest> {
var status = StatusReserva.n;
Future<void> _showMyDialog(BuildContext context) async {
return showDialog<void>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: const Text(
' ',
),
content: SingleChildScrollView(
child: ListBody(
children: const <Widget>[
Text(
'Confirmar reserva para o dia XX/XX/XX?',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 15,
fontFamily: 'Raleway',
fontWeight: FontWeight.bold),
),
],
),
),
actions: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(
child: const Text('Sim'),
onPressed: () => setState(() {
Navigator.pop(context);
status = StatusReserva.n;
}),
),
TextButton(
child: const Text('Não'),
onPressed: () => setState(() {
Navigator.pop(context);
status = StatusReserva.y;
}),
),
],
),
],
);
},
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0,
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
width: 100,
height: 100,
child: Container(
color: statusToColor(status),
child: const Center(
child: Text(
'Status color',
style: TextStyle(color: Colors.white),
)),
),
),
ElevatedButton(
onPressed: () {
_showMyDialog(context);
},
child: const Text('Show dialog'),
),
],
),
),
);
}
}
For further clarification
The StatusReserva status = StatusReserva.n; should be in the State class _DaysOfWeekMealsScreenState. And to change it use setState. This value should never change if not inside a setState.
The Sim button onPressed should be like the following (Also with fixes of an unintended Set creation):
TextButton(
child: const Text('Sim'),
onPressed: () {
_incrementCount();
Navigator.pop(context);
setState(() => status = StatusReserva.y);
},
),
Use a boolean value instead of enum like this
bool isCancelReservar = false;
and in the state class before build method add this code :
bool isCancelReservar = false;
#override
void initState(){
isCancelReservar = widget.isCancelReservar;
super.initState();
}
Now you are able to update the value of isCancelReservar on clicking "sim button" using setState method. Your text button should look like this :
TextButton(
child: const Text('Sim'),
onPressed: () {
setState(() {
isCancelReservar = true;
});
_incrementCount,
Navigator.pop(context);
},
),
and your elevated button like this :
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
),
margin: const EdgeInsets.all(10),
child: ElevatedButton(
onPressed: () => {_showMyDialog(context)},
style: ButtonStyle(
shape: MaterialStateProperty.all(RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
)),
padding: MaterialStateProperty.all(const EdgeInsets.all(15)),
backgroundColor:
MaterialStateProperty.all(isCancelReservar ? Colors.red :
Colors.green),
),
child: Text(isCancelReservar ? "Cancelar Reserva" : "Reservar"),
),
),
where you can see the backgroundColor will be red with text "Cancelar Reserva" if the value of isCancelReservar is true else it would be of color green with test Reservar.

Flutter: How to replace icon image from the list of pictures to chose from?

For instance: I have a main Icon so when you click on it, it opens a pop-up window with smaller icons/images to select from. So if you select one of the pictures from that pop-up it replaces the main Icon to that specific image.
I have spent hours trying to figure out how to replace icon images but nothing seems to work.
I have created an example (I have used flutter_speed_dial to make expandable buttons but it's not necessary). You can adjust it to your needs:
class _TestState extends State<Test> {
var fabIcon = Icons.expand_less;
var button1Icon = Icons.home;
var button2Icon = Icons.shop;
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
floatingActionButton: SpeedDial(
icon: fabIcon,
backgroundColor: Color(0xFF801E48),
visible: true,
curve: Curves.bounceIn,
children: [
// FAB 1
SpeedDialChild(
child: Icon(button1Icon),
backgroundColor: Color(0xFF801E48),
onTap: () {
var temp = fabIcon;
setState(() {
fabIcon = button1Icon;
button1Icon = temp;
});
},
labelStyle: TextStyle(
fontWeight: FontWeight.w500,
color: Colors.white,
fontSize: 16.0),
labelBackgroundColor: Color(0xFF801E48)),
// FAB 2
SpeedDialChild(
child: Icon(button2Icon),
backgroundColor: Color(0xFF801E48),
onTap: () {
var temp = fabIcon;
setState(() {
fabIcon = button2Icon;
button2Icon = temp;
});
},
labelStyle: TextStyle(
fontWeight: FontWeight.w500,
color: Colors.white,
fontSize: 16.0),
labelBackgroundColor: Color(0xFF801E48))
],
),
),
);
}
}
Using showDialog(...) is the solution.
Hope this will help you and others.
you can look at this example:
import 'package:flutter/material.dart';
class IconDialogScreen extends StatefulWidget {
const IconDialogScreen({Key? key}) : super(key: key);
#override
State<IconDialogScreen> createState() => _IconDialogScreenState();
}
class _IconDialogScreenState extends State<IconDialogScreen> {
IconData icon = Icons.abc;
List<IconData> icons = [
Icons.abc,
Icons.person_add,
Icons.person,
Icons.person_remove,
];
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(
child: TextButton(
onPressed: onIconClicked,
child: Wrap(
crossAxisAlignment: WrapCrossAlignment.center,
spacing: 20,
children: [Icon(icon, size: 50), const Text("change icon")],
),
),
)
],
),
);
}
void onIconClicked() async {
IconData? _icon = await showDialog<IconData?>(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('Select one icon'),
content: Wrap(
spacing: 10,
runSpacing: 10,
children: icons.map<Widget>((e) {
return ElevatedButton(
onPressed: () {
Navigator.of(context).pop(e);
},
child: Icon(e, size: 50));
}).toList(),
),
);
},
);
if (_icon != null) {
setState(() {
icon = _icon;
});
}
}
}

I cannot update UI state with riverpod

I'm working on a quiz app as a personal project and what I want to do is make it possible for the user to name a question set. (Kind of like a folder for questions on a particular subject). I am using Riverpod. (I've worked with the provider package a couple of times) for state management but it seems I've missed a step or two because when I type in the name, I don't see it on the page. I hope I can be pointed in the right direction. Thanks
Class forRiverpod model which shows a list of type QuestionSetConstructor for taking the title. There is also a method for accepting the question title to add to the list
class RiverpodModel extends ChangeNotifier {
final List<QuestionSetConstructor> _questionSetList = [];
UnmodifiableListView<QuestionSetConstructor> get questionSet {
return UnmodifiableListView(_questionSetList);
}
void addTitleT(String title) {
final addQuestionTitle = (QuestionSetConstructor(title: title));
_questionSetList.add(addQuestionTitle);
notifyListeners();
}
int get count{
return questionSet.length;
}
}
`
This is for the alert dialog that will take the question title.
In the elevated button, I stated that I want the contents of the
text field to be added to the list in the Riverpod model.
void setQuestionNameMethod(context) {
showDialog(
context: context,
barrierDismissible: true,
builder: (BuildContext context) {
return SetQuestionNameAlertDialog();
});
}
class SetQuestionNameAlertDialog extends ConsumerStatefulWidget {
#override
_SetQuestionNameAlertDialogState createState() =>
_SetQuestionNameAlertDialogState();
}
class _SetQuestionNameAlertDialogState
extends ConsumerState<SetQuestionNameAlertDialog> {
final TextEditingController questionNameController = TextEditingController();
final riverPodModelProvider2 =
ChangeNotifierProvider((ref) => RiverpodModel());
#override
Widget build(
BuildContext context,
) {
final questionNameRef = ref.watch(riverPodModelProvider2);
return AlertDialog(
title: Text("Name of Question Set",
style: TextStyle(
color: Colors.blue[400],
fontSize: 20,
fontWeight: FontWeight.w600)),
content: TextField(
controller: questionNameController,
),
actions: [
Center(
child: ElevatedButton(
onPressed: () {
setState(() {
questionNameRef.addTitleT(questionNameController.text) ;
});
print(questionNameRef.questionSet.first.title);
Navigator.pop(context);
},
child: const Text("Save"))),
],
);
}
}
`
This is the page where the question title is shown as a list. However, for some reason it is not showing.
class QuestionSetPage extends ConsumerStatefulWidget {
#override
_QuestionSetPageState createState() => _QuestionSetPageState();
}
class _QuestionSetPageState extends ConsumerState<QuestionSetPage> {
final riverPodModelProvider =
ChangeNotifierProvider((ref) => RiverpodModel());
#override
Widget build(BuildContext context) {
final questionSetRef = ref.watch(riverPodModelProvider);
return Scaffold(
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.grey[50],
centerTitle: true,
actions: [
IconButton(
onPressed: () {
setState(() {
setQuestionNameMethod(context);
// modalSheetMethod(context);
});
},
icon: Icon(
Icons.add,
size: 25,
color: Colors.blue[400],
))
],
),
body: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"Question Set List",
style: TextStyle(
color: Colors.blue[400],
fontSize: 30,
fontWeight: FontWeight.w600),
),
),
Expanded(
child: ListView.builder(
itemCount: questionSetRef.count,
itemBuilder: (BuildContext context, int index) {
return Tiles(
title: questionSetRef.questionSet[index].title,
);
}),
)
],
),
);
}
}
class Tiles extends StatelessWidget {
String title;
Tiles({required this.title});
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.fromLTRB(15, 3, 15, 3),
child: Material(
elevation: 2,
child: GestureDetector(
onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (context) {
return QuestionSetsQuestionPage();
}));
},
child: ListTile(
title: Text(
title,
style: TextStyle(
color: Colors.blue[400],
fontSize: 17,
fontWeight: FontWeight.w400),
),
tileColor: Colors.white,
// subtitle: Text(
// "${questionSets[index].numberOfQuestions} number of questions",
// ),
leading: const Icon(
Icons.add_box_outlined,
size: 30,
),
),
),
),
);
}
}