Need to change color of selected RadioListTile to green if user selects correct answer and red when wrong answer is selected - flutter

I am creating an multiple choice quiz app using flutter, currently when user selects an answer in radio list tile it, will check for correct answer and show a toast message.
Need to update the code to highlight selected answer with green color if answer is correct
and red if the answer is wrong.
If any idea please update the code and share the code. Thanks in advance.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:mechanicalaptitude/quiz/models/category.dart';
import 'package:mechanicalaptitude/quiz/models/question.dart';
import 'package:mechanicalaptitude/quiz/ui/pages/quiz_finished.dart';
import 'package:html_unescape/html_unescape.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:admob_flutter/admob_flutter.dart';
class QuizPage extends StatefulWidget {
final List<Question> questions;
final Category category;
const QuizPage({Key key, #required this.questions, this.category})
: super(key: key);
#override
_QuizPageState createState() => _QuizPageState();
}
class _QuizPageState extends State<QuizPage> {
final TextStyle _questionStyle = TextStyle(
fontSize: 18.0, //font size of the questions
fontWeight: FontWeight.bold,
color: Colors.red);
int _currentIndex = 0;
int i = 0;
int hint_index = 0;
var option1;
final Map<int, dynamic> _answers = {};
final GlobalKey<ScaffoldState> _key = GlobalKey<ScaffoldState>();
#override
Widget build(BuildContext context) {
Question question = widget.questions[_currentIndex];
final List<dynamic> options = question.incorrectAnswers;
if (!options.contains(question.correctAnswer)) {
options.add(question.correctAnswer);
//options.shuffle();
}
return WillPopScope(
onWillPop: _onWillPop,
child: Scaffold(
key: _key,
appBar: AppBar(
title: Text("Question No. - " + "${_currentIndex + 1}"),
backgroundColor: Colors.indigoAccent,
elevation: 10,
),
body: Center(
child: ListView(
shrinkWrap: true,
padding: EdgeInsets.all(15.0),
children: <Widget>[
Center(
child: Card(
elevation: 0.0,
child: Container(
//padding: EdgeInsets.all(0.0),
width: double.infinity,
height: 900,
child: Column(
children: <Widget>[
Row(
children: <Widget>[
//SizedBox(width: 10.0),
Expanded(
child: Text(
HtmlUnescape().convert(
widget.questions[_currentIndex].question),
softWrap: true,
textAlign: TextAlign.justify,
style: _questionStyle,
),
),
],
),
Row(
children: <Widget>[
//SizedBox(width: 10.0),
Expanded(
child: Image.network(
HtmlUnescape().convert(
widget.questions[_currentIndex].qimgurl),
// width: 300,
fit: BoxFit.fitWidth,
loadingBuilder: (BuildContext context,
Widget child,
ImageChunkEvent loadingProgress) {
if (loadingProgress == null) return child;
return Center(
child: CircularProgressIndicator(
value: loadingProgress.expectedTotalBytes !=
null
? loadingProgress
.cumulativeBytesLoaded /
loadingProgress.expectedTotalBytes
: null,
),
);
},
)),
],
),
//SizedBox(height: 0.0),
Card(
//elevation: 10.0,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
...options.map((option) => RadioListTile(
title: Text(
HtmlUnescape().convert("$option"),
style: TextStyle(color: Colors.black),
),
groupValue: _answers[_currentIndex],
value: option,
onChanged: (value) {
setState(() {
_answers[_currentIndex] = option;
if (i == 0) {
option1 = option;
}
if (option ==
widget.questions[_currentIndex]
.correctAnswer) {
i = 1;
Fluttertoast.cancel();
Fluttertoast.showToast(
msg: "Righ Answer",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.green,
textColor: Colors.white,
fontSize: 16.0);
} else {
i = 1;
Fluttertoast.cancel();
Fluttertoast.showToast(
msg: "Wrong Answer",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0);
}
});
},
)),
],
),
),
Expanded(
child: Container(
alignment: Alignment.topCenter,
child: new Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
/* const SizedBox(height: 30),*/
/* RaisedButton(
child: Text('Hint'),
onPressed:_giveHint,
color:Colors.yellow, ),*/
const SizedBox(),
ButtonTheme(
minWidth: 200,
height: 50,
child: RaisedButton(
child: Text(_currentIndex ==
(widget.questions.length - 1)
? "Submit"
: "Next"),
onPressed: _nextSubmit,
color: Colors.yellow,
),
),
],
),
),
)
],
),
),
),
),
],
),
),
),
);
}
void _nextSubmit() {
if (_answers[_currentIndex] == null) {
_key.currentState.showSnackBar(SnackBar(
content: Text("You must select an answer to continue."),
));
return;
}
if (_currentIndex < (widget.questions.length - 1)) {
_answers[_currentIndex] = option1;
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('Answer is'),
content: Text(widget.questions[_currentIndex].correctAnswer),
actions: <Widget>[
FlatButton(
child: Text('Ok'),
onPressed: () {
Navigator.of(context).pop();
setState(() {
_currentIndex++;
i = 0;
});
},
),
],
);
});
} else {
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (_) => QuizFinishedPage(
questions: widget.questions, answers: _answers)));
}
}
Future<bool> _onWillPop() async {
return showDialog<bool>(
context: context,
builder: (_) {
return AlertDialog(
content: Text(
"Are you sure you want to quit the quiz? All your progress will be lost."),
title: Text("Warning!"),
actions: <Widget>[
FlatButton(
child: Text("Yes"),
onPressed: () {
Navigator.pop(context, true);
},
),
FlatButton(
child: Text("No"),
onPressed: () {
Navigator.pop(context, false);
},
),
],
);
});
}
}

There is an activeColor property in RadioListTile which lets you change color of the tile when it's selected.You can add a condition using ternary operator as follows to do the work for you:
activeColor: (option ==
widget.questions[_currentIndex]
.correctAnswer) ? Colors.green : Colors.red,
Complete Code:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:mechanicalaptitude/quiz/models/category.dart';
import 'package:mechanicalaptitude/quiz/models/question.dart';
import 'package:mechanicalaptitude/quiz/ui/pages/quiz_finished.dart';
import 'package:html_unescape/html_unescape.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:admob_flutter/admob_flutter.dart';
class QuizPage extends StatefulWidget {
final List<Question> questions;
final Category category;
const QuizPage({Key key, #required this.questions, this.category})
: super(key: key);
#override
_QuizPageState createState() => _QuizPageState();
}
class _QuizPageState extends State<QuizPage> {
final TextStyle _questionStyle = TextStyle(
fontSize: 18.0, //font size of the questions
fontWeight: FontWeight.bold,
color: Colors.red);
int _currentIndex = 0;
int i = 0;
int hint_index = 0;
var option1;
final Map<int, dynamic> _answers = {};
final GlobalKey<ScaffoldState> _key = GlobalKey<ScaffoldState>();
#override
Widget build(BuildContext context) {
Question question = widget.questions[_currentIndex];
final List<dynamic> options = question.incorrectAnswers;
if (!options.contains(question.correctAnswer)) {
options.add(question.correctAnswer);
//options.shuffle();
}
return WillPopScope(
onWillPop: _onWillPop,
child: Scaffold(
key: _key,
appBar: AppBar(
title: Text("Question No. - " + "${_currentIndex + 1}"),
backgroundColor: Colors.indigoAccent,
elevation: 10,
),
body: Center(
child: ListView(
shrinkWrap: true,
padding: EdgeInsets.all(15.0),
children: <Widget>[
Center(
child: Card(
elevation: 0.0,
child: Container(
//padding: EdgeInsets.all(0.0),
width: double.infinity,
height: 900,
child: Column(
children: <Widget>[
Row(
children: <Widget>[
//SizedBox(width: 10.0),
Expanded(
child: Text(
HtmlUnescape().convert(
widget.questions[_currentIndex].question),
softWrap: true,
textAlign: TextAlign.justify,
style: _questionStyle,
),
),
],
),
Row(
children: <Widget>[
//SizedBox(width: 10.0),
Expanded(
child: Image.network(
HtmlUnescape().convert(
widget.questions[_currentIndex].qimgurl),
// width: 300,
fit: BoxFit.fitWidth,
loadingBuilder: (BuildContext context,
Widget child,
ImageChunkEvent loadingProgress) {
if (loadingProgress == null) return child;
return Center(
child: CircularProgressIndicator(
value: loadingProgress.expectedTotalBytes !=
null
? loadingProgress
.cumulativeBytesLoaded /
loadingProgress.expectedTotalBytes
: null,
),
);
},
)),
],
),
//SizedBox(height: 0.0),
Card(
//elevation: 10.0,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
...options.map((option) => RadioListTile(
title: Text(
HtmlUnescape().convert("$option"),
style: TextStyle(color: Colors.black),
),
activeColor: (option ==
widget.questions[_currentIndex]
.correctAnswer) ? Colors.green : Colors.red,
groupValue: _answers[_currentIndex],
value: option,
onChanged: (value) {
setState(() {
_answers[_currentIndex] = option;
if (i == 0) {
option1 = option;
}
if (option ==
widget.questions[_currentIndex]
.correctAnswer) {
i = 1;
Fluttertoast.cancel();
Fluttertoast.showToast(
msg: "Righ Answer",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.green,
textColor: Colors.white,
fontSize: 16.0);
} else {
i = 1;
Fluttertoast.cancel();
Fluttertoast.showToast(
msg: "Wrong Answer",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0);
}
});
},
)),
],
),
),
Expanded(
child: Container(
alignment: Alignment.topCenter,
child: new Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
/* const SizedBox(height: 30),*/
/* RaisedButton(
child: Text('Hint'),
onPressed:_giveHint,
color:Colors.yellow, ),*/
const SizedBox(),
ButtonTheme(
minWidth: 200,
height: 50,
child: RaisedButton(
child: Text(_currentIndex ==
(widget.questions.length - 1)
? "Submit"
: "Next"),
onPressed: _nextSubmit,
color: Colors.yellow,
),
),
],
),
),
)
],
),
),
),
),
],
),
),
),
);
}
void _nextSubmit() {
if (_answers[_currentIndex] == null) {
_key.currentState.showSnackBar(SnackBar(
content: Text("You must select an answer to continue."),
));
return;
}
if (_currentIndex < (widget.questions.length - 1)) {
_answers[_currentIndex] = option1;
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('Answer is'),
content: Text(widget.questions[_currentIndex].correctAnswer),
actions: <Widget>[
FlatButton(
child: Text('Ok'),
onPressed: () {
Navigator.of(context).pop();
setState(() {
_currentIndex++;
i = 0;
});
},
),
],
);
});
} else {
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (_) => QuizFinishedPage(
questions: widget.questions, answers: _answers)));
}
}
Future<bool> _onWillPop() async {
return showDialog<bool>(
context: context,
builder: (_) {
return AlertDialog(
content: Text(
"Are you sure you want to quit the quiz? All your progress will be lost."),
title: Text("Warning!"),
actions: <Widget>[
FlatButton(
child: Text("Yes"),
onPressed: () {
Navigator.pop(context, true);
},
),
FlatButton(
child: Text("No"),
onPressed: () {
Navigator.pop(context, false);
},
),
],
);
});
}
}

Related

Flutter|Updating a ListView

everyone!
I have a HomeScreen, with this code:
return SafeArea(
child: Scaffold(
body: Stack(
children: [
Padding(
padding: const EdgeInsets.only(left: 8, right: 8),
child: Column(children: [
ActiveTaskInfo(
task: tasks.first,
),
const TextWidget(),
Expanded(child: TasksList()),
const SizedBox(height: 80),
]),
),
BottomBarClass(),
],
),
),
);
TasksList() - ListView.
BottomBarClass() - It is a container with a button inside.
If you return the code itself to the main HomeScreen file, everything works, but if you put it in a separate class and when you add a new item to the list (through the button) nothing happens, but if you press Hot Reload, then the new item in the list is displayed.
Code BottomBarClass():
Positioned(
bottom: 0, left: 0,
child: ClipRRect(
borderRadius: const BorderRadius.only(topRight: Radius.circular(30), topLeft: Radius.circular(30)),
child: Container(
height: 80, width: MediaQuery.of(context).size.width,
color: const Color(0xff070417),
child: Row(mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Icon(Icons.watch_later, color: Colors.white.withOpacity(0.4)),
IconButton(icon: Icon(Icons.add, color: Colors.white.withOpacity(0.4),), iconSize: 32, onPressed: () async {
bool result = await Navigator.push(context, MaterialPageRoute(builder: (context) {
return TaskAdding();
}));
if (result == true) {
setState(() {
});
}
}),
Icon(Icons.pie_chart_rounded, color: Colors.white.withOpacity(0.4), size: 24,),
],),
),
));
Вот пример GIF: https://gifyu.com/image/Spp1O
TaskAdding():
import 'package:flutter/material.dart';
import '../expansions/task_tags_decorations.dart';
import '../expansions/tasks_data.dart';
class TaskAdding extends StatefulWidget {
const TaskAdding({Key? key}) : super(key: key);
#override
State<TaskAdding> createState() => _TaskAddingState();
}
class _TaskAddingState extends State<TaskAdding> {
late String _addField;
late Widget _selectedValue;
late bool _active;
late int _selectedIndex;
#override
void initState() {
_addField = 'Empty';
_active = false;
_selectedValue = tasks[0].icon;
_selectedIndex = 0;
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Add'), backgroundColor: Colors.pink),
body: Column(children: [
Text('Add Task', style: TextStyle(color: Colors.white, fontSize: 24),),
TextField(onChanged: (String value) {
_addField = value;
}),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
DropdownButton<Widget>(
value: _selectedValue,
onChanged: (newValue) {
setState(() {
_selectedValue = newValue!;
});
},
items: dropdownItems,
),
ElevatedButton(
onPressed: () {
setState(() {
tasks.addAll({
TaskData(
taskName: _addField,
tagOne: _active
? tasks[0].tagOne
: tasks[1].tagOne,
tagTwo: tagTwoContainer[_selectedIndex],
icon: _selectedValue,
taskTime: '00:32:10',
)
});
decorations.addAll({
TaskTagsDecorations(
iconColor: const Color(0xff7012CF))
});
});
Navigator.of(context).pop(true);
},
child: const Text('Add')),
],
),
Center(
child: ListTile(
title: _active
? Center(
child: tasks[0].tagOne,
)
: Center(child: tasks[1].tagOne),
selected: _active,
onTap: () {
setState(() {
_active = !_active;
});
},
),
),
SizedBox(
height: 52,
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: tagTwoContainer.length,
itemBuilder: (context, index) {
var tagTwoList = tasks[index].tagTwo;
return SizedBox(
height: MediaQuery.of(context).size.height, width: 160,
child: ListTile(
visualDensity: VisualDensity.compact,
selected: index == _selectedIndex,
selectedTileColor: Colors.indigo.withOpacity(0.6),
title: Align(
alignment: Alignment.topCenter,
child: tagTwoList),
onTap: () {
setState(() {
_selectedIndex = index;
});
},
),
);
}),
),
],),
);
}
List<DropdownMenuItem<Widget>> get dropdownItems {
List<DropdownMenuItem<Widget>> menuItems = [
DropdownMenuItem(
child: const Icon(Icons.free_breakfast),
value: iconCircle[0],
),
DropdownMenuItem(
child: const Icon(Icons.grade_outlined), value: iconCircle[1]),
DropdownMenuItem(child: const Icon(Icons.gamepad), value: iconCircle[2]),
DropdownMenuItem(
child: const Icon(Icons.face_rounded), value: iconCircle[3]),
];
return menuItems;
}
}
You question is not clear. Try to add TasksList()
My solution:
Navigator.push(context,
MaterialPageRoute(builder: (context) {
return HomeScreen();
}));

The class 'SimpleFoldingCell' doesn't have a default constructor

https://github.com/flutter-devs/flutter_folding_cell_demo/blob/master/lib/demo_screen.dart
I'm trying to follow the code in the link above.
But in the SimpleFoldingCell part, an error named 'The class 'SimpleFoldingCell' doesn't have a default constructor.' occurs.
Could
Is there a way to resolve this error in Dart?
class Notific extends StatefulWidget{
#override
_State createState() => _State();
}
class _State extends State<Notific>{
late List<TechnologyModel> _technologyList;
#override
void initState() {
super.initState();
_technologyList = [
TechnologyModel(title: "Application Development",),
TechnologyModel(title: "Research & Development",),
TechnologyModel(title: "Big Data & Analytics",),
TechnologyModel(title: "Support Services",),
TechnologyModel(title: "QA & Software Testing",),
];
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
backgroundColor: Colors.pink[200],
title: Text("Folding Cell Demo",
style: TextStyle(color: Colors.white),),
),
body: Container(
child: ListView.builder(
itemCount: _technologyList.length,
itemBuilder: (context, index) {
return SimpleFoldingCell(
frontWidget: _buildFrontWidget(index),
innerTopWidget: _buildInnerWidget(index),
innerBottomWidget: _buildInnerBottomWidget(),
cellSize: Size(MediaQuery.of(context).size.width, 125),
padding: EdgeInsets.all(15),
animationDuration: Duration(milliseconds: 200),
borderRadius: 10,
onOpen: () => print('$index cell opened'),
onClose: () => print('$index cell closed'),
);
},
),
),
);
}
Widget _buildFrontWidget(int index) {
return Builder(
builder: (BuildContext context) {
return Container(
color: Colors.cyan[100],
alignment: Alignment.bottomCenter,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Aeologic Technology",
style: TextStyle(
fontSize:20.0,
color: Colors.black,
),
),
SizedBox(height: 10,),
FlatButton(
onPressed: () {
final foldingCellState = context
.findAncestorStateOfType<SimpleFoldingCellState>();
foldingCellState?.toggleFold();
},
child: Text(
"OPEN",
),
textColor: Colors.white,
color: Colors.indigoAccent[100],
splashColor: Colors.white.withOpacity(0.5),
),
],
),
);
},
);
}
Widget _buildInnerBottomWidget() {
return Builder(
builder: (context) {
return Container(
color: Colors.blueGrey[50],
alignment: Alignment.bottomCenter,
child: Padding(
padding: EdgeInsets.only(bottom: 10),
child: FlatButton(
onPressed: () {
final foldingCellState = context
.findAncestorStateOfType<SimpleFoldingCellState>();
foldingCellState?.toggleFold();
},
child: Text(
"Close",
),
textColor: Colors.white,
color: Colors.redAccent[100],
splashColor: Colors.white.withOpacity(0.5),
),
),
);
}
);
}
Widget _buildInnerWidget(int index) {
return Builder(
builder: (context) {
return Container(
color: Colors.pink[100],
padding: EdgeInsets.only(top: 10),
child: Align(
alignment: Alignment.center,
child: Text(
_technologyList[index].title,
style: TextStyle(
fontSize:20.0,
color: Colors.black,
),
),
),
);
},
);
}
}
class TechnologyModel {
String title;
TechnologyModel({
required this.title,
});
}
For some reason they've created only a named constructor.
return SimpleFoldingCell.create(
frontWidget: _buildFrontWidget(index),
innerWidget: _buildInnerWidget(index),
// innerTopWidget: _buildInnerWidget(index),
// innerBottomWidget: _buildInnerBottomWidget(),
cellSize: Size(MediaQuery.of(context).size.width, 125),
padding: EdgeInsets.all(15),
animationDuration: Duration(milliseconds: 200),
borderRadius: 10,
onOpen: () => print('$index cell opened'),
onClose: () => print('$index cell closed'),
);
It looks like the demo you're looking at is a bit outdated, since some of those properties don't exist anymore (see commented code).

Why am I having memory issues with flutter ChangeNotifierProvider?

I am making a shopping cart app in flutter with Change Notifier Provider. It is working fast and well at first. But it takes the more memory, the more I use it. I am adding and removing clearing items from list. Nothing complicated. Cannot know why it is working like this. It is slowing down gradually. This is main.dart:
class Main extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => Cart(),
child: MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: swatchColor,
primaryColor: primaryColor,
accentColor: tertiaryColor,
textSelectionTheme: TextSelectionThemeData(
cursorColor: Colors.black,
selectionColor: primaryColor,
selectionHandleColor: primaryColor,
),
),
initialRoute: '/login',
routes: {
'/home': (context) => Home(),
'/login': (context) => Login(),
'/tableReview': (context) => TableReview(),
'/createOrder': (context) => CreateOrder(),
'/orderReview': (context) => OrderReview(),
},
),
);
}
}
This is main cart_model.dart
import 'package:counter/data/models/cart_item.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
class Cart extends ChangeNotifier {
List<Item> cart = [];
addItemToCart({#required item}) {
Item newItem = Item(
id: item.id,
price: item.price is int ? item.price : int.parse(item.price),
title: item.title,
);
int i = cart.indexWhere((previousItem) => previousItem.id == newItem.id);
if (i > -1) {
cart[i].count++;
} else {
cart.add(newItem);
}
notifyListeners();
}
removeItemFromCart({#required item}) {
int index = cart.indexWhere((element) => element.id == item.id);
if (index > -1) {
if (cart[index].count > 1) {
cart[index].count--;
} else {
cart.removeWhere((element) => element.id == item.id);
}
}
notifyListeners();
}
clearCart() {
cart.clear();
notifyListeners();
}
int get totalPrice =>
cart.fold(0, (total, current) => total + (current.price * current.count));
}
This is menuitem.dart
class MenuItem extends StatelessWidget {
final dynamic foodItem;
MenuItem({#required this.foodItem});
void _showSecondPage(BuildContext context) {
Navigator.of(context).push(
MaterialPageRoute(
builder: (ctx) => Scaffold(
backgroundColor: Colors.black45,
body: Center(
child: Hero(
tag: foodItem.imgPath,
child: Image(image: NetworkImage(base_url + foodItem.imgPath)),
),
),
),
),
);
}
#override
Widget build(BuildContext context) {
int itemIndex = Provider.of<Cart>(context, listen: false)
.cart
.indexWhere((item) => item.id == foodItem.id);
return Container(
height: 80,
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
GestureDetector(
onTap: () => _showSecondPage(context),
child: Hero(
tag: foodItem.imgPath,
child: CircleAvatar(
backgroundImage: NetworkImage(base_url + foodItem.imgPath),
),
),
),
SizedBox(
width: 15,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text(
foodItem.title,
style: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 17,
),
),
Text('${foodItem.price.toString()} сум'),
],
)
],
),
Container(
width: 160,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon:
Icon(Icons.remove, color: Theme.of(context).primaryColor),
onPressed: () {
Provider.of<Cart>(context, listen: false)
.addItemToCart(item: foodItem);
},
),
Text(
itemIndex > -1
? '${Provider.of<Cart>(context).cart[itemIndex].count}'
: '0',
style: TextStyle(fontSize: 18),
),
IconButton(
icon: Icon(Icons.add, color: Theme.of(context).primaryColor),
onPressed: () {
Provider.of<Cart>(context, listen: false)
.addItemToCart(item: foodItem);
},
),
],
),
),
],
),
);
}
}
This is consumer part:
import 'package:counter/common/socketio.dart';
import 'package:counter/data/models/cart_model.dart';
import 'package:counter/presentation/widgets/empty_cart.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
class OrderReview extends StatefulWidget {
#override
_OrderReviewState createState() => _OrderReviewState();
}
class _OrderReviewState extends State<OrderReview> {
bool isCommentEnabled = false;
String guestCount;
String comment = '';
final _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
final myCart = context.watch<Cart>();
return Scaffold(
resizeToAvoidBottomInset: true,
appBar: AppBar(
title: Text('Проверка заказа'),
),
body: Builder(
builder: (context) {
if (myCart.cart.length > 0) {
handleOrderCreate() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String userId = prefs.getString('userId');
String tableNum = prefs.getString('tableNum');
String status = 'accepted';
print('$userId, $tableNum, $status');
Map orderToCreate = {
'tableNum': tableNum,
'status': 'accepted',
'userId': userId,
'guestCount': guestCount,
'comment': comment,
'foodList': myCart.cart
};
socketIO.emit('createOrder', json.encode(orderToCreate));
Navigator.of(context).pushNamed('/home');
Provider.of<Cart>(context, listen: false).clearCart();
}
return GestureDetector(
onTap: () => FocusScope.of(context).requestFocus(new FocusNode()),
child: LayoutBuilder(
builder:
(BuildContext context, BoxConstraints viewportConstraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight,
),
child: IntrinsicHeight(
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 8.0, vertical: 8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Form(
key: _formKey,
child: Column(
children: [
Container(
height: 350,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10),
topRight: Radius.circular(10),
bottomLeft: Radius.circular(10),
bottomRight: Radius.circular(10)),
boxShadow: [
BoxShadow(
color:
Colors.grey.withOpacity(0.5),
spreadRadius: 5,
blurRadius: 7,
offset: Offset(0,
3), // changes position of shadow
),
]),
child: ListView.separated(
itemBuilder:
(BuildContext context, int i) {
return ListTile(
title: Text(myCart.cart[i].title),
trailing: Container(
width: 160,
child: Row(
crossAxisAlignment:
CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: <Widget>[
IconButton(
icon: Icon(
Icons.remove,
color: Theme.of(context)
.primaryColor,
),
onPressed: () {
Provider.of<Cart>(context,
listen: false)
.removeItemFromCart(
item: myCart
.cart[i]);
},
),
Text(
'${myCart.cart[i].count}',
style:
TextStyle(fontSize: 18),
),
IconButton(
icon: Icon(
Icons.add,
color: Theme.of(context)
.primaryColor,
),
onPressed: () {
Provider.of<Cart>(context,
listen: false)
.addItemToCart(
item: myCart
.cart[i]);
},
),
],
),
),
);
},
separatorBuilder:
(BuildContext context, int) {
return Divider(
height: 2,
color: Colors.grey,
);
},
itemCount: myCart.cart.length,
),
),
SizedBox(height: 20),
Container(
child: TextFormField(
keyboardType: TextInputType.number,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'Количество гостей',
),
onChanged: (newValue) {
setState(() => guestCount = newValue);
},
validator: (value) {
if (value == null || value.isEmpty) {
return 'Пожалуйста, введите количество гостей!';
}
return null;
},
),
),
SizedBox(height: 20),
Container(
child: TextFormField(
onChanged: (newValue) {
setState(() => comment = newValue);
},
enabled: isCommentEnabled,
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText:
'Лаваш острый, хот дог без майонеза и т.д.',
// labelText: 'Комментарий',
),
maxLines: 2,
),
),
Row(
children: [
Text('Комментарий'),
Switch(
value: isCommentEnabled,
onChanged: (bool value) {
setState(() =>
this.isCommentEnabled = value);
},
),
],
)
],
),
),
SizedBox(height: 20),
Row(
children: [
Text(
'Общая цена: ',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w500,
),
),
SizedBox(width: 20),
Text(
'${myCart.totalPrice} сум',
style: TextStyle(fontSize: 18),
),
],
),
Container(
height: 50,
width: 170,
child: ElevatedButton(
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.resolveWith(
(states) =>
Theme.of(context).primaryColor),
),
onPressed: () {
if (_formKey.currentState.validate()) {
handleOrderCreate();
}
},
child: Text(
'Отправить',
style: TextStyle(
color: Colors.white, fontSize: 18),
),
),
),
],
),
),
),
),
);
},
),
);
} else {
print('111');
return EmptyCart();
}
},
),
);
}
}
Is there something wrong with my code?

Flutter General dialog box - set state not working

I have an issue with my General Dialog Box. I would like to display a star. Then I would like to change it state when the star is taped and replace the icon by a yellow Star.
But is does not work. The Dialog Box is not refreshed so the icon is not changing. Please, can you look at the source code below and point me into the right direction please?
Many thanks.
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:date_time_picker/date_time_picker.dart';
import 'package:gtd_official_sharped_focused/snackbar.dart';
String _isImportantInboxTask ;
String _isUrgentInboxTask ;
String inboxTaskDisplayed;
String isImportant = "false" ;
String isUrgent = "false" ;
String myProjectName ;
var taskSelectedID;
//---------------
//String _initialValue;
//_-----------------
var documentID;
var textController = TextEditingController();
var popUpTextController = TextEditingController();
class Inbox extends StatefulWidget {
Inbox({Key key}) : super(key: key);
#override
_InboxState createState() => _InboxState();
}
class _InboxState extends State<Inbox> {
GlobalKey<FormState> _captureFormKey = GlobalKey<FormState>();
bool isOn = true;
#override
Widget build(BuildContext context) {
void showAddNote() {
TextEditingController _noteField = new TextEditingController();
showDialog(
context: context,
builder: (BuildContext context) {
return CustomAlertDialog(
content: Container(
width: MediaQuery.of(context).size.width / 1.3,
height: MediaQuery.of(context).size.height / 4,
child: Column(
children: [
TextField(
controller: _noteField,
maxLines: 4,
decoration: InputDecoration(
border: const OutlineInputBorder(
borderSide:
const BorderSide(color: Colors.black, width: 1.0),
),
),
),
SizedBox(height: 10),
Material(
elevation: 5.0,
borderRadius: BorderRadius.circular(25.0),
color: Colors.white,
child: MaterialButton(
minWidth: MediaQuery.of(context).size.width / 1.5,
onPressed: () {
Navigator.of(context).pop();
CollectionReference users = FirebaseFirestore.instance
.collection('Users')
.doc(FirebaseAuth.instance.currentUser.uid)
.collection('allTasks');
users
.add({'task_Name': _noteField.text,'task_Status': 'Inbox' })
.then((value) => print("User Document Added"))
.catchError((error) =>
print("Failed to add user: $error"));
},
padding: EdgeInsets.fromLTRB(10.0, 15.0, 10.0, 15.0),
child: Text(
'Add Note',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20.0,
color: Colors.black,
fontWeight: FontWeight.bold,
),
),
),
),
],
),
),
);
});
}
return Scaffold(
appBar: new AppBar(
title: new Text('Inbox Page'),
actions: <Widget>[
IconButton(
icon: Icon(
Icons.add_circle_outline,
color: Colors.white,
),
onPressed: () {
showAddNote();
// do something
},
),
],
),
drawer: MyMenu(),
backgroundColor: Colors.white,
body: Column(
//mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
height: MediaQuery.of(context).size.height / 1.4,
width: MediaQuery.of(context).size.width,
child: StreamBuilder(
stream: FirebaseFirestore.instance
.collection('Users')
.doc(FirebaseAuth.instance.currentUser.uid)
.collection('allTasks')
.where('task_Status', isEqualTo: 'Inbox')
.snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
return ListView(
children: snapshot.data.docs.map((document) {
return Wrap(
children: [Card(
child: SwipeActionCell(
key: ObjectKey(document.data()['task_Name']),
actions: <SwipeAction>[
SwipeAction(
title: "delete",
onTap: (CompletionHandler handler) {
CollectionReference users = FirebaseFirestore
.instance
.collection('Users')
.doc(
FirebaseAuth.instance.currentUser.uid)
.collection('allTasks');
users
.doc(document.id)
.delete()
.then((value) => print("Note Deleted"))
.catchError((error) => print(
"Failed to delete Task: $error"));
},
color: Colors.red),
],
child: Padding(
padding: const EdgeInsets.all(0.0),
child: ListTile(
leading: ConstrainedBox(
constraints: BoxConstraints(
minWidth: leadingIconMinSize,
minHeight: leadingIconMinSize,
maxWidth: leadingIconMaxSize,
maxHeight: leadingIconMaxSize,
),
child: Image.asset('assets/icons/inbox.png'),
),
title: GestureDetector(
child: Text(
//'task_Name' correspond au nom du champ dans la table
document.data()['task_Name'],
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
// Pour editer task
onDoubleTap: (){
taskSelectedID = FirebaseFirestore
.instance
.collection('Users')
.doc(
FirebaseAuth.instance.currentUser.uid)
.collection('allTasks')
.doc(document.id);
//Dialog
return showGeneralDialog(
context: context,
barrierDismissible: true,
barrierLabel: MaterialLocalizations.of(context)
.modalBarrierDismissLabel,
barrierColor: Colors.black45,
transitionDuration: const Duration(milliseconds: 20),
pageBuilder: (BuildContext buildContext,
Animation animation,
Animation secondaryAnimation) {
return Scaffold(
appBar: AppBar(
title: Text ('Edit Task'),
leading: InkWell(
child: Icon(Icons.close),
onTap:(){Navigator.of(context).pop();}
),
actions: [Padding(
padding: const EdgeInsets.fromLTRB(0, 0,16.0,0),
child: InkWell(
child: Icon(Icons.save),
onTap: () {
final loFormInbox = _captureFormKey
.currentState;
if (loFormInbox.validate()) {
loFormInbox.save();
CollectionReference users = FirebaseFirestore
.instance
.collection(
'Users')
.doc(FirebaseAuth
.instance
.currentUser.uid)
.collection(
'allTasks');
users
.add({
'task_Name': _valueTaskNameSaved,
})
.then((value) =>
print(
"Task Created"))
.catchError((
error) =>
print(
"Failed to add task: $error"));
showSimpleFlushbar(
context,
'Task Saved',
_valueTaskNameSaved,
Icons
.mode_comment);
loFormInbox.reset();
isImportant = 'false';
isUrgent = 'false';
}
}
),
)],
),
body: Center(
child: Container(
width: MediaQuery.of(context).size.width - 10,
height: MediaQuery.of(context).size.height - 80,
padding: EdgeInsets.all(20),
color: Colors.white,
child: Column(
children: [
Theme(
data: ThemeData(
inputDecorationTheme: InputDecorationTheme(
border: InputBorder.none,
)
),
child: Padding(
padding: const EdgeInsets.fromLTRB(8.0, 0.0, 15.0, 1.0),
child: TextFormField(
initialValue: document.data()['task_Name'],
decoration: InputDecoration(hintText: "Task Name"),
maxLength: 70,
maxLines: 2,
onChanged: (valProjectName) => setState(() => _valueTaskNameChanged = valProjectName),
validator: (valProjectName) {
setState(() => _valueTaskNameToValidate = valProjectName);
return valProjectName.isEmpty? "Task name cannot be empty" : null;
},
onSaved: (valProjectName) => setState(() => _valueTaskNameSaved = valProjectName),
),
)),
//Test Energy et Time / Important /urgent
Material(
child:
Container(
// color: Colors.red,
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children:[
//Important
FlatButton(
child:
InkWell(
child: Container(
// color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
isImportant =="true" ? Icon(Icons.star,color: Colors.orange,) :
Icon(Icons.star_border, color: Colors.grey,),
// Icon(Icons.battery_charging_full),
Text('Important'),
],
)
),
onTap: () {
setState(() {
if (isImportant=='true'){
isImportant = 'false';}
else
{isImportant= 'true';
}
});
},
),
),
RaisedButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text(
"Close",
style: TextStyle(color: Colors.white),
),
color: const Color(0xFF1BC0C5),
)
//++++++++++++++++
],
),
),
),
);
});
},
),
),
),
),
),
),
]
);
}).toList(),
);
}),
),
],
),
bottomNavigationBar: MyBottomAppBar(), //PersistentBottomNavBar(),
);
}
}
#override
Widget build(BuildContext context){
return _widget();
}
}
Thanks to your solution, I am able to do what I was willing to do. But now, I have an other issue. In the version 1 of my code, I am using this code
Theme(
data: ThemeData(
inputDecorationTheme: InputDecorationTheme(
border: InputBorder.none,
)
),
child: Padding(
padding: const EdgeInsets.fromLTRB(8.0, 0.0, 15.0, 1.0),
child: TextFormField(
initialValue: document.data()['task_Name'],
decoration: InputDecoration(hintText: "Task Name"),
maxLength: 70,
maxLines: 2,
onChanged: (valProjectName) => setState(() => _valueTaskNameChanged = valProjectName),
validator: (valProjectName) {
setState(() => _valueTaskNameToValidate = valProjectName);
return valProjectName.isEmpty? "Task name cannot be empty" : null;
},
onSaved: (valProjectName) => setState(() => _valueTaskNameSaved = valProjectName),
),
)),
This part was working well. But after the modifications, I am getting an error. The error is about document.
Undefined name 'document'. Try correcting the name to one that is defined, or defining the name.
Please, can you help me with this so I can finalize this page. Thank you
So you want to change the color of icon on clicking it inside dialogBox,
but unfortunately you are using stateless widget Scaffold in return of showGeneralDialog builder so one thing that can possibly help is to make a separate StateFull Widget RatingDialogBox and use that in the builder.
Also instead of InkWell you can use IconButton
I will suggest you to use this package it is great
flutter_rating_bar
also feel free to comment is this doesn't satisfy your need

Prevent keyboard from appearing on Flutter

I made this very simple aplication but im having a problem with it.
On every action that i do (like deleting something) the keyboard opens automatically.
I want to avoid that, and open the keyboard only when i click on the text form field (line 178 on code).
How can i do that?
I know this is something very simple to make, i have tried some things using focusnode, trying to disable the autofocus, but i didnt could make it work the way i need.
import 'dart:convert';
import 'dart:ffi';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
import 'package:http/http.dart' as http;
void main() {
runApp(MaterialApp(
home: Pedidos(),
));
}
class Pedidos extends StatefulWidget {
#override
_PedidosState createState() => _PedidosState();
}
class _PedidosState extends State<Pedidos> with TickerProviderStateMixin {
TabController _tabController;
final _pecasController = TextEditingController();
List _pecasList = [];
var _firstPress = true;
#override
void initState() {
super.initState();
_tabController = new TabController(length: 3, vsync: this);
}
void _addPecas() {
if ((_pecasController.text.isEmpty) ||
((_pecasController.text.trimLeft() == ("")))) {
print("Campo Vazio");
} else {
setState(() {
Map<String, dynamic> newPeca = Map();
newPeca["title"] = _pecasController.text.trimLeft();
//newPeca["ok"] = false;
_pecasController.text = "";
_pecasList.add(newPeca);
// _saveData();
print(_pecasList);
});
}
}
void _enviar() {
if (_pecasList.length < 1) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text("Lista vazia"),
actions: <Widget>[
new FlatButton(
child: new Text("Fechar"),
onPressed: () {
Navigator.of(context).pop();
}),
]);
});
} else {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text("Deseja enviar os itens?"),
actions: <Widget>[
new FlatButton(
child: new Text("Fechar"),
onPressed: () {
Navigator.of(context).pop();
}),
new FlatButton(
child: new Text("Enviar"),
onPressed: () async {
Map<String, String> headers = new Map<String, String>();
headers["Content-type"] = "application/json";
headers["Accept"] = "application/json";
//String str = '{"take":55, "skip":"0"}';
final resp = await http.post('http://172.16.14.109:5000/',
//body: str,
body: jsonEncode(_pecasList),
headers: headers);
if (resp.statusCode == 200) {
if (resp.body == "ok") {
setState(() {
print(_pecasList);
_pecasList.clear();
Navigator.of(context).pop();
});
} else {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text(
"Erro: entre em contato com o suporte."),
actions: <Widget>[
new FlatButton(
child: new Text("Fechar"),
onPressed: () {
Navigator.of(context).pop();
Navigator.of(context).pop();
}),
]);
});
}
}
})
],
);
},
);
}
}
void _apagarTudo() {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text("Deseja limpar a lista?"),
actions: <Widget>[
new FlatButton(
child: new Text("Fechar"),
onPressed: () {
Navigator.of(context).pop();
}),
new FlatButton(
child: new Text("Limpar"),
onPressed: () {
setState(() {
_pecasList.clear();
Navigator.of(context).pop();
});
}),
]);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
"Solicitação de Peças",
style: TextStyle(fontWeight: FontWeight.bold),
),
centerTitle: true,
backgroundColor: Colors.green,
),
body: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: <Widget>[
Expanded(
flex: 8,
child: TextFormField(
controller: _pecasController,
keyboardType: TextInputType.text,
style: TextStyle(
color: Colors.black,
fontSize: 18,
),
decoration: InputDecoration(
hintText: ("Adicionar item"),
),
),
),
Padding(
padding: EdgeInsets.only(right: 15),
),
Expanded(
flex: 2,
child: RaisedButton(
child: Icon(Icons.add, color: Colors.amber),
color: Colors.green,
onPressed: _addPecas,
),
)
],
),
),
Divider(
height: 02.0,
),
Expanded(
child: ListView.builder(
itemCount: _pecasList.length,
itemBuilder: (context, index) {
return ListTile(
dense: true,
key:
Key(DateTime.now().millisecondsSinceEpoch.toString()),
title: Text(
_pecasList[index]["title"],
style: TextStyle(fontSize: 15.0),
),
trailing: Icon(
Icons.delete_forever,
color: Colors.redAccent,
),
onLongPress: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title:
new Text("Deseja remover o item da lista?"),
actions: <Widget>[
new FlatButton(
child: new Text("Fechar"),
onPressed: () {
Navigator.of(context).pop();
},
),
new FlatButton(
child: new Text("Excluir"),
onPressed: () {
_pecasList.removeAt(index);
setState(() {
Navigator.of(context).pop();
});
},
),
],
);
},
);
});
}),
),
Row(
mainAxisAlignment: (MainAxisAlignment.center),
children: <Widget>[
Padding(
padding: const EdgeInsets.all(10.0),
child: RaisedButton(
color: Colors.green,
padding: EdgeInsets.all(5.0),
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(4.0),
child: Icon(
Icons.send,
color: Colors.white,
),
),
Padding(
padding: const EdgeInsets.all(2.0),
child: Text(
"Enviar",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
],
),
onPressed: _enviar,
)),
Padding(
padding: const EdgeInsets.all(10.0),
child: RaisedButton(
color: Colors.redAccent,
padding: EdgeInsets.all(5.0),
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(4.0),
child: Icon(
Icons.delete,
color: Colors.white,
),
),
Padding(
padding: const EdgeInsets.all(2.0),
child: Text(
"Limpar",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
],
),
onPressed: () {
_apagarTudo();
}))
],
)
],
),
);
}
}
Try these changes.
I have controlled enabled field of TextFormField. The TextFormField is disabled when you click on RaisedButton to add the item to list. And TextFormField is enabled when you click on itself.
void _addPecas() {
disableTextFormField();
...
}
bool textFormFieldEnabled = true;
void enableTextFormField(){
setState(() {
textFormFieldEnabled = true;
});
}
void disableTextFormField(){
setState(() {
textFormFieldEnabled = false;
});
}
Widget build(BuildContext context) {
....
child: TextFormField(
controller: _pecasController,
keyboardType: TextInputType.text,
enabled: textFormFieldEnabled,
onTap: () => enableTextFormField(),
style: TextStyle(
color: Colors.black,
fontSize: 18,
),
decoration: InputDecoration(
hintText: ("Adicionar item"),
),
),
...
}