Flutter OnTap Listview item - flutter

I'm new to flutter, may I know how to get different outputs when I click on each item? I have total of 3 lists, for each item, I want to get their respective output and now I only can get the same outputs for each item. How to get different outputs when I click on it? Thanks all.
this is my ListView coding :
class _CatState extends State<Cat> {
List<String> categories = ["Furniture", "Lighting", "Decoration"];
int selectedIndex = 0;
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 5.0),
child: SizedBox(
height: 25,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: categories.length,
itemBuilder: (context, index) => buildCategory(index),
),
));
}
Widget buildCategory(int index) {
return GestureDetector(
onTap: () {
setState(() {
selectedIndex = index;
});
},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 40.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
categories[index],
style: TextStyle(
fontSize: 15,
color: selectedIndex == index ? Colors.black : Colors.black45,
),
),
Container(
margin: EdgeInsets.only(top: DefaultPadding / 4), //top padding
height: 2,
width: 50,
color: selectedIndex == index
? Colors.blueAccent[200]
: Colors.transparent,
)
],
When onTap the item:
class ItemCard extends StatelessWidget {
final Product product;
final Decor decoration;
final Light light;
final Function press;
const ItemCard({
Key key,
this.press,
this.product,
this.decoration,
this.light,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: press,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
child: Container(
padding: EdgeInsets.all(2.0),
// height: 180,
// width: 160,
child: ClipRRect(
borderRadius: BorderRadius.circular(25.0),
child: Image.asset(
product.img, // products image
)),
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: DefaultPadding / 4),
child: Text(
product.name, // products name
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
),
Text(
product.price,
textAlign: TextAlign.center,
style: TextStyle(fontStyle: FontStyle.italic),
)
],
),

Use switch case if it is static. For example on itemBuilder in Gridview:
ItemCard(
product:furniture[index],
press: _onPressed(index),
)
and in onPressed method, do whatever you want:
_onPressed(int index){
switch(index):
case 0:
your code:
break;
case 1:
//code
}
so by this you can make different onTap function

Related

How to update time dynamically in flutter

I have a list view with list tiles with each containing a region with its specific time.
I am using a Getx controller with the class WorldTime with two parameters location and time.
There is already a timer that's called during setState to update the clock widget, but how do I implement this to update each list tile time or is there any other way to update the time automatically without calling setState.
class _WorldClockState extends State<WorldClock> {
final WorldTimeController worldTimeController =
Get.put(WorldTimeController());
String formattedTime = DateFormat('h:mm').format(DateTime.now());
String hour = DateFormat('a').format(DateTime.now());
late Timer _timer;
#override
void initState() {
super.initState();
_timer =
Timer.periodic(const Duration(milliseconds: 500), (timer) => _update());
}
void _update() {
setState(() {
formattedTime = DateFormat('h:mm').format(DateTime.now());
hour = DateFormat('a').format(DateTime.now());
});
}
#override
void dispose() {
_timer.cancel();
super.dispose();
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
resizeToAvoidBottomInset: false,
body: SingleChildScrollView(
child: Column(
children: [
Padding(
padding: const EdgeInsets.only(top: 20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(formattedTime,
style: GoogleFonts.lato(
fontSize: 80.0,
color: Colors.blue,
fontStyle: FontStyle.normal,
letterSpacing: 5.0)),
Padding(
padding: const EdgeInsets.only(top: 40.0, left: 5.0),
child: Text(
hour,
style: GoogleFonts.lato(
color: Colors.blue,
fontSize: 30.0,
),
),
),
],
),
),
Container(
child: Text(
DateFormat('EE, MMM d').format(DateTime.now()),
style: GoogleFonts.lato(
color: Colors.white,
fontSize: 20.0,
letterSpacing: 2.0,
),
),
),
const Padding(
padding: EdgeInsets.only(top: 20.0, left: 30.0, right: 30.0),
child: Divider(
color: Colors.white,
height: 2.0,
),
),
GetBuilder<WorldTimeController>(
id: 'Clockid',
builder: (value) => Container(
height: 600.0,
width: 450.0,
child: Padding(
padding: const EdgeInsets.only(top: 20.0),
child: ListView.builder(
scrollDirection: Axis.vertical,
physics: const BouncingScrollPhysics(),
shrinkWrap: true,
itemCount: worldTimeController.WorldTimeList.length,
itemBuilder: (BuildContext context, index) => Padding(
padding: const EdgeInsets.only(bottom: 18.0),
child: Slidable(
key: UniqueKey(),
startActionPane: ActionPane(
motion: ScrollMotion(),
dismissible: DismissiblePane(onDismissed: () {
worldTimeController.WorldTimeList.removeAt(index);
}),
children: const [],
),
child: ListTile(
leading: Text(
worldTimeController
.WorldTimeList[index].location,
style: GoogleFonts.lato(
color: Colors.white70, fontSize: 25)),
trailing: Text(
'${value.getTime(worldTimeController.WorldTimeList[index].location)}',
style: GoogleFonts.lato(
color: Colors.white70, fontSize: 35.0),
),
),
),
),
),
),
),
),
],
),
),
floatingActionButton: Padding(
padding: const EdgeInsets.only(right: 192.0, bottom: 20.0),
child: FloatingActionButton(
onPressed: () {
Get.to(() => const RegionSelectScreen());
},
child: const Icon(Icons.public),
),
),
),
);
}
}
controller:
class WorldTimeController extends GetxController {
var WorldTimeList = <WorldTime>[].obs;
var newUrl;
var newResponse;
Future<dynamic> getTime(location) async {
newUrl = "http://worldtimeapi.org/api/timezone/${location}";
newResponse = await get(Uri.parse(newUrl));
Map newData = jsonDecode(newResponse.body);
var time = newData['datetime'];
String dateTime = newData["utc_datetime"];
String offset = newData["utc_offset"];
DateTime now = DateTime.parse(dateTime);
now = now.add(Duration(
hours: int.parse(offset.substring(1, 3)),
minutes: int.parse(offset.substring(4))));
update(['Clockid']);
return time = DateFormat.jm().format(now);
}
#override
void onInit() {
List? storedWorldTime = GetStorage().read<List>('WorldTime');
if (storedWorldTime != null) {
WorldTimeList.assignAll(
storedWorldTime.map((e) => WorldTime.fromJson(e)).toList());
}
ever(WorldTimeList, (_) {
GetStorage().write('WorldTime', WorldTimeList.toList());
});
super.onInit();
}
}
In your getXcontroller class you can create function to update the hours and on this function you can add
update(['clockId']);
then in your screen
return GetBuilder<WorldTimeController>(
id: 'clockId',
init: WorldTimeController(), // If is init this line is not necessary
builder: (worldTimeController) => Container(
height: 600.0,
width: 450.0,
child: Padding(
padding: const EdgeInsets.only(top: 20.0),
child: ListView.builder(
scrollDirection: Axis.vertical,
physics: const BouncingScrollPhysics(),
shrinkWrap: true,
itemCount: worldTimeController.WorldTimeList.length,
itemBuilder: (BuildContext context, index) => Padding(
padding: const EdgeInsets.only(bottom: 18.0),
child: Slidable(
key: UniqueKey(),
startActionPane: ActionPane(
motion: ScrollMotion(),
dismissible: DismissiblePane(onDismissed: () {
worldTimeController.WorldTimeList.removeAt(
index);
}),
children: [],
),
child: ListTile(
leading: Text(
'${worldTimeController.WorldTimeList[index].location}',
style: GoogleFonts.lato(
color: Colors.white70, fontSize: 25)),
trailing: Text(
"${worldTimeController.WorldTimeList[index].time}",
style: GoogleFonts.lato(
color: Colors.white70, fontSize: 35.0),
),
),
),
)),
),
),
);
Then even that change something in your function this will refresh all the list inside your clockId.
Try to avoid setState because this method rebuild all the view and when your app grows does't has good performance
Here an example:
https://github.com/alcampospalacios/GetX_UpdateAll_Example

Widget not redrawing despite Setstate & UniqueKey

I have this code for selecting options in a product page.
The index is updating well, but the color of the selected option refuses to change (as well as the name of the selected option on the right -- see the image below), and i can't figure why..
I have tried to use Setstate(), and to use unique keys for the related parent widgets
Here the image:
import 'package:animate_do/animate_do.dart';
import 'package:flutter/material.dart';
import 'package:prem_market/models/product.dart';
import 'package:prem_market/models/product_variation.dart';
class DisplayAttributes extends StatefulWidget {
const DisplayAttributes({
Key key,
this.data,
Function onChanged,
}) : super(key: key);
final Product data;
#override
_DisplayAttributesState createState() => _DisplayAttributesState();
}
class _DisplayAttributesState extends State<DisplayAttributes> {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
int activeOption = 0;
return Column(
children: [
...List.generate(
this.widget.data.attributes.length,
(index) => !this.widget.data.attributes[index].variation
? SizedBox()
: Column(
children: <Widget>[
SizedBox(
height: 25,
),
Padding(
padding: EdgeInsets.only(left: 25, right: 25),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
FadeInDown(
delay: Duration(milliseconds: 450),
child: Text(
this.widget.data.attributes[index].name,
style: TextStyle(
fontSize: 16, fontWeight: FontWeight.w600),
),
),
FadeInDown(
delay: Duration(milliseconds: 450),
child: Text(
activeOption == 100
? '-'
: this
.widget
.data
.attributes[index]
.options[activeOption],
style: TextStyle(
fontSize: 16,
//color: black.withOpacity(0.7)
),
),
)
],
)),
SizedBox(
height: 25,
),
FadeInDown(
delay: Duration(milliseconds: 500),
child: Padding(
padding: EdgeInsets.only(left: 20, right: 25),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: this
.widget
.data
.attributes[index]
.options
.asMap()
.map<int, GestureDetector>(
(i, String childData) {
return MapEntry(
i,
GestureDetector(
key: UniqueKey(),
onTap: () {
setState(() {
if (activeOption == i) {
//selected = false;
activeOption = 100;
} else {
activeOption = i;
//selected = true;
}
});
FocusScope.of(context)
.requestFocus(new FocusNode());
},
child: Padding(
padding: const EdgeInsets.only(
right: 15,
bottom: 5,
left: 5,
top: 5),
child: Container(
key: UniqueKey(),
//width: 50,
height: 50,
padding: EdgeInsets.symmetric(
horizontal: 10),
decoration: BoxDecoration(
color: activeOption == i
? Theme.of(context)
.textTheme
.headline6
.color
: Colors.grey[200],
borderRadius:
BorderRadius.circular(8),
boxShadow: [
BoxShadow(
spreadRadius: 0.5,
blurRadius: 1,
color: Theme.of(context)
.shadowColor
.withOpacity(0.1))
]),
child: Center(
child: Text(
childData,
key: UniqueKey(),
style: TextStyle(
fontSize: 16,
color: activeOption == i
? Theme.of(context)
.backgroundColor
: Theme.of(context)
.shadowColor),
),
),
),
),
));
})
.values
.toList(),
),
),
),
),
],
),
),
],
);
}
}
You are resetting activeOption to 0 in build function make it a global variable. Everytime you call setState() build method is called which again resets it to 0
#override
Widget build(BuildContext context) {
int activeOption = 0;
to
int activeOption = 0;
#override
Widget build(BuildContext context) {

Change state from another widget in flutter?

I am trying to make a cart icon with a text of the number of items in the cart. This requires a state refresh when state refreshes in another widget. Even though not recommended, I tried setState(), but as warned the widget was not mounted so setState() was called on null.
Then I came to know about Value listenable from this post How to set state from another widget?
I tried this, but it says "NoSuchMethodError: the getter 'value' was called on null, maybe my implementation was wrong.
heres my code:
var menuJson = [];
var isLoading = true;
class CartIcon extends StatefulWidget {
const CartIcon({Key key2}) : super(key: key2);
#override
_CartIcon createState() => _CartIcon();
}
class _CartIcon extends State<CartIcon> {
#override
Widget build(BuildContext context) {
var filteredList = List();
for (var item in menuJson) {
if (item["quantity"] > 0) {
filteredList.add(item);
}
}
return Padding(
padding: const EdgeInsets.only(top: 35, right: 8),
child: Container(
width: AppBar().preferredSize.height - 12,
height: AppBar().preferredSize.height - 12,
color: Colors.pink,
child: Material(
color: Colors.transparent,
child: InkWell(
borderRadius: BorderRadius.circular(AppBar().preferredSize.height),
child: Stack(
children: <Widget>[
IconButton(
icon: Icon(
Icons.shopping_cart,
color: Colors.white,
),
onPressed: null,
),
filteredList.length == 0
? Container()
: Positioned(
child: Stack(
children: <Widget>[
Icon(Icons.brightness_1,
size: 20.0, color: Colors.green[800]),
Positioned(
top: 3.0,
right: 4.0,
child: Text(
filteredList.length.toString(),
style: TextStyle(
color: Colors.white,
fontSize: 11.0,
fontWeight: FontWeight.w500),
))
],
)),
],
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => CartPage()),
);
},
),
),
),
);
}
}
class Salads extends StatefulWidget {
const Salads({Key key2}) : super(key: key2);
#override
_Salads createState() => _Salads();
}
class _Salads extends State<Salads> {
final _counter = new ValueNotifier(0);
plus(index) {
var quant = menuJson[index]["quantity"];
quant++;
menuJson[index]["quantity"] = quant;
setState(() {});
}
minus(index) {
var quant = menuJson[index]["quantity"];
quant--;
if (quant < 0) {
quant = 0;
}
menuJson[index]["quantity"] = quant;
setState(() {});
}
#override
Widget build(BuildContext context) {
var filteredList = List();
for (var item in menuJson) {
if (item["category_name"] == "Salads") {
filteredList.add(item);
}
}
if (isLoading) {
return Center(
child: new CircularProgressIndicator(),
);
} else {
return Container(
color: Colors.green,
child: ListView.builder(
itemCount: filteredList.length,
itemBuilder: (context, index) {
return Card(
child: Padding(
padding: const EdgeInsets.only(
top: 10.0, bottom: 10.0, left: 10.0, right: 10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
padding: EdgeInsets.only(
left: 5, top: 5, bottom: 30),
child: Text(
filteredList[index]["dish_name"],
style: TextStyle(fontSize: 20),
textAlign: TextAlign.left,
),
),
Container(
padding: EdgeInsets.only(
right: 5, top: 5, bottom: 30),
child: Text(
'\u{20B9} ' +
filteredList[index]["price"]
.toString(),
style: TextStyle(
color: Colors.grey.shade600,
fontSize: 20),
textAlign: TextAlign.right,
)),
]),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
RawMaterialButton(
onPressed: () =>
plus(filteredList[index]["index"]),
child: new Icon(
Icons.add,
color: Colors.black,
),
fillColor: Colors.white,
shape: CircleBorder(),
),
Text(filteredList[index]["quantity"].toString(),
style: new TextStyle(fontSize: 40.0)),
RawMaterialButton(
onPressed: () =>
minus(filteredList[index]["index"]),
child: new Icon(
const IconData(0xe15b,
fontFamily: 'MaterialIcons'),
color: Colors.black,
),
fillColor: Colors.white,
shape: CircleBorder(),
padding: EdgeInsets.all(0),
)
])
],
)));
}),
);
}
}
}
Since cart icon is in the app bar, it is higher in the widget tree.
How can I make such that when + is pressed in 'Salads' the CartIcon state updates in the appbar? Right now it updates the state when i tap on the cart button.
Maybe use a Global Key?
GlobalKey<_CartIcon> cartKey = GlobalKey<_CartIcon>();
When making your CartIcon insert the globalKey.
Make a new Method inside _CartIcon:
refresh(){
setState((){})
}
and when you want to refresh your CartIcon call:
cartKey.currentState.refresh();

How to add a plus Button in ListView Builder fetches the data from SQLite in Flutter

I have a ListView Builder where I have one Stateful Widget. I want to add a plus Button as Widget inside the ListView Item. What I am doing is that, I have added a number of records in SQLite when creating the database, and I have added a plus Icon and an empty as record/row to the database. So I am fetching the data from there. The Plus Button(Widget) is displaying as I expect but when update the data into the database the Button is not Showing at the Expected position, Because I want it to display at the end of all the items.
class CategoriesScreen extends StatefulWidget {
#override
_CategoriesScreenState createState() => _CategoriesScreenState();
}
class _CategoriesScreenState extends State<CategoriesScreen> {
List<Map<String,dynamic>> spendingCategoriesList=[] ;
DatabaseHelper helper=DatabaseHelper();
#override
Widget build(BuildContext context) {
getData();
return Scaffold(
backgroundColor: Color(0xFF343641),
body: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height-100,
margin: EdgeInsets.only(top: 40.0),
child: Column(
children: <Widget>[
Container(
width:MediaQuery.of(context).size.width ,
height: 30.0,
margin: EdgeInsets.only(left: 20.0),
child: Row(
children: [
GestureDetector(
onTap:(){Navigator.pop(context);},
child: Icon(
Icons.close,
color: Color(0xFFE44663),
size: 24.0,
),
),
Padding(
padding: EdgeInsets.only(left:MediaQuery.of(context).size.width*0.3),
child: Text('Categories',style: TextStyle(color: Colors.white,fontWeight: FontWeight.normal,fontSize: 15.0,),),
),
],
),
),
Expanded(
child: GridView.builder(
itemCount: spendingCategoriesList.length,
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3), itemBuilder: (context,index){
AddTransactionsModel transactionModel= new AddTransactionsModel(spendingCategoriesList[index]['CategoryImage'],spendingCategoriesList[index]['categoryName']);
return AddTransactionItem(transactionModel);
}),
),
],
),
),
);
}
void getData() async{
spendingCategoriesList=await helper.getNoteMapList();
setState(() {
spendingCategoriesList=spendingCategoriesList;
});
}
Here is the AddTransactionGridItem;
class _AddTransactionItemState extends State<AddTransactionItem> {
var imageSelectIndex;
String categoryName;
String categoryImage;
#override
Widget build(BuildContext context) {
print(
'Hello dear ! icon Number ${widget.transactionModel.iconNumber} and here is Text ${widget.transactionModel.categoryNumber} ');
return Container(
child: Column(
children: <Widget>[
InkWell(
onTap: widget.transactionModel.categoryNumber == ''
? () {
showAddCategoryDialogue();
}
: () {
setState(() {
categoryName=widget.transactionModel.categoryNumber;
categoryImage=widget.transactionModel.iconNumber;
print('categoryName $categoryName And categoryImage $categoryImage');
String cate='$categoryName&$categoryImage';
Navigator.pop(context,cate);
});
},
child: Container(
width: 72.0,
height: 72.0,
decoration: BoxDecoration(
color: Color(0xffC4C4C4).withOpacity(0.2),
borderRadius: BorderRadius.all(Radius.circular(12.0)),
border: widget.transactionModel.categoryNumber == ''
? Border.all(width: 0.3, color: Colors.white)
: Border.all(width: 0.0),
),
child: Center(
child: Image.asset('${widget.transactionModel.iconNumber}')),
),
),
SizedBox(
height: 10.0,
),
Text(
widget.transactionModel.categoryNumber,
style: TextStyle(
color: Colors.white,
fontSize: 16.0,
fontWeight: FontWeight.w600,
fontFamily: 'Rajdhani',
fontStyle: FontStyle.normal),
)
],
),
);
}
AboveContainer is the ListView.Builder() Item .

Stateful widget not updating, after being updated in setState, how to solve this?

I am new to Flutter. I am trying to build a Quiz App. Now, I am on the Quiz Screen, and then a quiz has multiple questions. I am showing the question title along with the answers, and when someone clicks on the answer, I am updating the QuestionView again with the new question data. These are stateful widgets, and when the result is fetched I am using setState to update the widget, and if I place a break point there I can see that the things are updated, but that is not rendered on the screen or the view is not changed, it has same title, answers and everything. I am using an optionTap method and you can find it in the comments below. I have mentioned where I am tapping the option and what is done below it.
Here's what I have done so far:
import 'package:flutter/material.dart';
import 'package:flutter_app/Constants/constants.dart';
import 'package:flutter_app/Models/question_model.dart';
import 'package:flutter_app/ViewModels/QuestionsVM.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
QuizQuestionViewModel questionViewModel = QuizQuestionViewModel();
QuizQuestionModel _questionModel;
Widget updateWidget;
class SQQuiz extends StatefulWidget {
final QuizQuestionModel quizQuestionModel;
final int quizId;
SQQuiz({Key key, #required this.quizQuestionModel, #required this.quizId})
: super(key: key);
#override
_SQQuizState createState() =>
_SQQuizState(quizQuestionModel: quizQuestionModel, quizId: quizId);
}
class _SQQuizState extends State<SQQuiz> {
final QuizQuestionModel quizQuestionModel;
final int quizId;
_SQQuizState(
{Key key, #required this.quizQuestionModel, #required this.quizId});
#override
Widget build(BuildContext context) {
_questionModel = quizQuestionModel;
updateWidget = QuestionView(
quizQuestionModel: _questionModel,
quizId: quizId,
);
return Scaffold(
appBar: AppBar(
leading: Container(
child: Row(
children: <Widget>[
IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(Icons.arrow_back),
),
],
),
),
title: Padding(
padding: const EdgeInsets.symmetric(horizontal: 0),
child: Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Text(
_questionModel.questionDetail.quizName,
style: TextStyle(color: Constants.greyColor, fontSize: 12),
textAlign: TextAlign.left,
),
SizedBox(
width: 14,
),
CircularProgressIndicator(
value: 15,
strokeWidth: 2,
),
],
),
),
),
actions: <Widget>[
Container(
margin: const EdgeInsets.only(right: 10),
child: Center(
child: Container(
child: Text("SCORE ${_questionModel.score}"),
),
),
)
],
),
body: SafeArea(child: updateWidget),
);
}
}
class QuestionView extends StatefulWidget {
final QuizQuestionModel quizQuestionModel;
final int quizId;
QuestionView(
{Key key, #required this.quizQuestionModel, #required this.quizId})
: super(key: key);
#override
_QuestionViewState createState() => _QuestionViewState(
quizQuestionModel: quizQuestionModel,
quizId: quizId,
);
}
class _QuestionViewState extends State<QuestionView> {
final QuizQuestionModel quizQuestionModel;
final int quizId;
_QuestionViewState({#required this.quizQuestionModel, #required this.quizId});
#override
Widget build(BuildContext context) {
QuestionDetail questionDetail = quizQuestionModel.questionDetail;
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
SizedBox(
height: 10,
),
Text(
"Question ${quizQuestionModel.count}/${quizQuestionModel.totalCount}",
style: TextStyle(fontSize: 12),
),
SizedBox(
height: 5,
),
Image(
image: NetworkImage(
questionDetail.pic,
),
fit: BoxFit.cover,
),
Container(
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 50),
color: Constants.orangeColor,
child: Text(
questionDetail.title,
style: TextStyle(
color: Colors.white,
fontSize: 16,
),
textAlign: TextAlign.center,
),
),
ListView.builder(
itemBuilder: (context, index) {
Answers answers = questionDetail.answers[index];
return Card(
elevation: 5,
margin:
const EdgeInsets.symmetric(vertical: 10, horizontal: 0),
child: ListTile(
onTap: () { //This is where I am tapping the option
optionTap(
context: context,
sessionId: quizQuestionModel.sessionId,
quizId: quizId,
questionId: questionDetail.questionId,
answerId: answers.id,
hintUsed: false,
fiftyUsed: false,
).then((response) {
setState(() { //Here the updateWidget is updated, which you can see in the body, but it is not rendered
_questionModel = response;
updateWidget = new QuestionView(
quizQuestionModel: response,
quizId: quizId,
); // The new QuestionView with new details
});
});
},
contentPadding: const EdgeInsets.symmetric(vertical: 10),
title: Text(
answers.title,
textAlign: TextAlign.center,
),
),
);
},
itemCount: questionDetail.answers.length,
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
),
SizedBox(
height: 20,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
RaisedButton(
padding: const EdgeInsets.symmetric(horizontal: 50),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5),
),
onPressed: () {
print("50-50 Tapped");
},
child: Text(
"50 | 50\n ${quizQuestionModel.fiftyCoin} coins",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
),
),
),
Wrap(
spacing: 3,
children: <Widget>[
Icon(FontAwesomeIcons.coins),
Text("${quizQuestionModel.coins}"),
],
),
RaisedButton(
padding: const EdgeInsets.symmetric(horizontal: 50),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5),
),
onPressed: () {
print("Hint Tapped");
},
child: Text(
"HINT\n ${quizQuestionModel.hintUsed} coins",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
),
),
)
],
),
],
)
],
);
}
There are no errors at the moment, can anyone please help me with this? Thanks in advance.
No offence - but I think you have completely misunderstood the concept of state management in flutter.
If you have a stateful widget, the setState() method triggers the build() method again. So setState is a notifier to say: Hey there was an update to our variable, please build again.
Your Stateful Widget is doing that. BUT there are no new updates on variables from that widget, because your variables ARE OUTSIDE of the widget. They won't get updated for your StatefulWidget. Consider to rethink you architecture. For small Apps it is enough to pass the variables in a constructor.
Here are some links to get closer to the Flutter-State-Management-Concept:
https://flutter.dev/docs/get-started/codelab
https://flutter.dev/docs/development/data-and-backend/state-mgmt/options