how to reduce the gap between this widgets? I tried tweaking padding values but no luck so far. Please take a look - flutter

This is the code
I tweaked the paading but no luck. I am new to flutter manage to build this but stuck, any suggestions/help is much appreciated!
import 'package:bmi_app_one/utils/TextStyle_Decorations.dart';
import 'package:bmi_app_one/utils/hexcolor.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_icons/flutter_icons.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class home_screen extends StatefulWidget {
#override
_home_screenState createState() => _home_screenState();
}
class _home_screenState extends State<home_screen> {
Color _appBar_bg_color = HexColor('#1C1C1E');
Color _app_bg_color = HexColor('#2c2c2e');
bool changeButtonColorMale = false;
bool changeButtonColorFemale = false;
int age = 20;
int weight = 30;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: homeScreenAppBarText,
backgroundColor: _appBar_bg_color,
centerTitle: true,
),
backgroundColor: _app_bg_color,
body: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
width: ScreenUtil().screenWidth,
height: 0.6.sh,
child: Row(
/* Entry Point of 1st set */
children: [
/* This contains both Male and female gender button */
Column(
children: [
Row(
children: [
/* Male Button */
Padding(
padding: const EdgeInsets.fromLTRB(8, 8, 4, 8),
child: InkWell(
onTap: (){
debugPrint("Gender: Male pressed");
setState(() {
if(changeButtonColorMale == false){
changeButtonColorMale = true;
changeButtonColorFemale = false;
}
else{
changeButtonColorMale = false;
}
});
},
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
child: Container(
width: 0.4.sw,
height: 0.2.sh,
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.1),
borderRadius: BorderRadius.circular(8.0)
),
margin: EdgeInsets.all(10),
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(12.0),
child: Icon(Ionicons.ios_male,size: 88.ssp,
color: changeButtonColorMale ? Colors.yellow.withOpacity(0.7) : Colors.white),
),
Text(
"Male", style: TextStyle(
fontSize: 24.ssp,
fontFamily: 'San francisco',
color: changeButtonColorMale ? Colors.yellow.withOpacity(0.7) : Colors.white
),
),
],
),
),
),
),
/* Age */
Padding(
padding: const EdgeInsets.fromLTRB(0, 8, 8, 8),
child: Container(
width: 0.43.sw,
height: 0.2.sh,
margin: EdgeInsets.all(10),
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.1),
borderRadius: BorderRadius.circular(8.0)
),
child: Column(
children: [
/* Age Text */
Padding(
padding: const EdgeInsets.fromLTRB(8, 36, 8, 8),
child: Text("AGE",
style: TextStyle(
fontSize: 24.ssp,
fontFamily: 'San francisco',
color: Colors.white
),
),
),
Row(
children: [
/* Age decrease icon */
Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
child: IconButton(
icon: new Icon(
MaterialCommunityIcons.minus_circle_outline,
size: 42.ssp,
color: Colors.white,),
onPressed: (){
debugPrint("Age decreased by 1");
setState(() {
if(age <= 5){
}
else{
age --;
}
});
},
splashRadius: 0.1,
),
),
/* Display Age in numbers */
Padding(
padding: const EdgeInsets.fromLTRB(15, 8 , 0, 0),
child: Text(age.toString(),
style: TextStyle(
color: Colors.white,
fontSize: 26.ssp,
fontFamily: 'San francisco',
),
),
),
/* Age increase icon */
Padding(
padding: const EdgeInsets.fromLTRB(3, 0, 0, 0),
child: IconButton(
icon: new Icon(
MaterialCommunityIcons.plus_circle_outline,
size: 42.ssp,
color: Colors.white,),
onPressed: (){
debugPrint("Age increased by 1");
setState(() {
if(age >= 90){
}
else{
age ++;
}
});
},
splashRadius: 0.1,
),
)
],
)
],
),
),
)
],
),
Row(
children: [
/* Female Button */
Padding(
padding: const EdgeInsets.fromLTRB(8, 0, 4, 0),
child: new InkWell(
onTap: (){
debugPrint("Gender: Female pressed");
setState(() {
if(changeButtonColorFemale == false){
changeButtonColorFemale = true;
changeButtonColorMale = false;
}
else{
changeButtonColorFemale = false;
}
});
},
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
child: Container(
width: 0.4.sw,
height: 0.2.sh,
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.1),
borderRadius: BorderRadius.circular(8.0)
),
margin: EdgeInsets.all(10.0),
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(12.0),
child: Icon(Ionicons.ios_female,size: 88.ssp,
color: changeButtonColorFemale ? Colors.yellow.withOpacity(0.7) : Colors.white),
),
Text(
"Female", style: TextStyle(
fontSize: 24.ssp,
fontFamily: 'San francisco',
color: changeButtonColorFemale ? Colors.yellow.withOpacity(0.7) : Colors.white
),
),
],
),
),
),
),
/* Weight */
Padding(
padding: const EdgeInsets.fromLTRB(0, 8, 8, 8),
child: Container(
width: 0.43.sw,
height: 0.2.sh,
margin: EdgeInsets.all(10),
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.1),
borderRadius: BorderRadius.circular(8.0)
),
child: Column(
children: [
/* Weight Text */
Row(
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(24, 36, 3, 8),
child: Text("WEIGHT",
style: TextStyle(
fontSize: 24.ssp,
fontFamily: 'San francisco',
color: Colors.white
),
),
),
Text("(Kg)",
style: TextStyle(
color: Colors.white.withOpacity(0.7),
fontSize: 11.ssp,
fontFamily: 'San francisco',
),
),
],
),
Row(
children: [
/* Weight decrease icon */
Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
child: IconButton(
icon: new Icon(
MaterialCommunityIcons.minus_circle_outline,
size: 42.ssp,
color: Colors.white,),
onPressed: (){
debugPrint("Weight decreased by 1");
setState(() {
if(weight <= 5){
}
else{
weight --;
}
});
},
splashRadius: 0.1,
),
),
/* Display Weight in numbers */
Padding(
padding: const EdgeInsets.fromLTRB(15, 8 , 0, 0),
child: Text(weight.toString(),
style: TextStyle(
color: Colors.white,
fontSize: 26.ssp,
fontFamily: 'San francisco',
),
),
),
/* Weight increase icon */
Padding(
padding: const EdgeInsets.fromLTRB(3, 0, 0, 0),
child: IconButton(
icon: new Icon(
MaterialCommunityIcons.plus_circle_outline,
size: 42.ssp,
color: Colors.white,),
onPressed: (){
debugPrint("Weight increased by 1");
setState(() {
if(weight >= 625){
}
else{
weight ++;
}
});
},
splashRadius: 0.1,
),
)
],
)
],
),
),
),
],
)
],
),
],
),
),
/* Height Slider 2nd set */
Container(
width: ScreenUtil().screenWidth,
height: 0.15.sh,
decoration: BoxDecoration(
color: Colors.white
),
child: Column(
children: [],
),
)
],
),
)
);
}
}
This is the screenshot at present
tweaked the paading but no luck. I am new to flutter manage to build this but stuck, any suggestions/help is much appreciated!

You're creating that extra space with how you're setting the height of the 2nd Container at the top of your build method. I assume that the sh in height: 0.6.sh, is ScreenHeight * 0.6?
It doesn't appear that either of those first 2 Container's are adding anything of value. You can just remove them both and your white Container at the bottom should jump up closer to everything else.

Related

create a fixed sized widget on flutter

I'm currently trying to create a row that consist of maximum 3 column widget with each of them have the property of profile picture, nickname, and status. I wanted each of them to have fixed size so that even when the nickname is long it will still take the same amount of space.
Currently I just make the column to be spaced-evenly and some of the widget still take more space than the other 2. How can I fixed this ? maybe make the nickname turned into dotted (...) when it's too long.
here's my current code:
solverWidgets.add(
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
BuildRoundedRectProfile(
height: 40,
width: 40,
name: solverTicket[solver]['nickname'],
profileLink: solverTicket[solver]['profile_picture_link'] ?? '',
),
SizedBox(height: 3),
Text(
solverTicket[solver]['nickname'],
style: weight600Style.copyWith(
color: primaryColor,
fontSize: 13,
),
),
if (solversStatus[solver] != null && (povStatus == 'pic' || povStatus == 'pic-client'))
GestureDetector(
onTap: () {
if (solversStatus[solver] == 'Done') {
setState(() {
needToLoadSolverWidgets = true;
isNotExpandedSolverWidgets[solver] = !isNotExpandedSolverWidgets[solver];
});
if (isExpandedSolverWidgetsContent[solver]) {
Future.delayed(Duration(milliseconds: 300), () {
setState(() {
needToLoadSolverWidgets = true;
isExpandedSolverWidgetsContent[solver] = false;
});
});
} else {
setState(() {
needToLoadSolverWidgets = true;
isExpandedSolverWidgetsContent[solver] = true;
});
}
}
},
child: AnimatedContainer(
duration: Duration(milliseconds: 300),
height: isNotExpandedSolverWidgets[solver] ? 20 : 55,
padding: EdgeInsets.only(top: 5, bottom: 5, left: 5, right: 5),
decoration: BoxDecoration(
color: defaultProfileColor.withOpacity(0.2),
borderRadius: BorderRadius.circular(10),
),
child: solversStatus[solver] != 'Done' ?
Text(
solversStatus[solver],
style: primaryColor600Style.copyWith(
fontSize: fontSize9,
),
).tr() : isNotExpandedSolverWidgets[solver] ?
Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
solversStatus[solver],
style: primaryColor600Style.copyWith(
fontSize: fontSize10,
),
).tr(),
Icon(
Icons.arrow_drop_down,
size: fontSize15,
),
],
) : ClipRRect(
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Row(
children: [
Text(
solversStatus[solver],
style: primaryColor600Style
.copyWith(
fontSize: fontSize9,
),
).tr(),
Icon(
Icons.arrow_drop_down,
size: fontSize18,
),
],
),
GestureDetector(
onTap: () {
showDialog(
context: context,
builder: (BuildContext
context) =>
ReusableConfirmationDialog(
titleText: 'changeWorkStatus'.tr(),
contentText: 'rejectWorkStatus'.tr(),
confirmButtonText: 'yes'.tr(),
onConfirm: () async {
await Database.changeWorkStatus(
ticketId: widget.ticketId,
ticketData: ticketData,
targetId: solver as String,
oldWorkStatus: 'done',
workStatus: 'todo');
Navigator.pop(context);
setState(() {
isNotExpandedSolverWidgets[solver] = true;
needToLoadTicket = true;
});
}));
},
child: Container(
padding: EdgeInsets.all(5),
decoration: BoxDecoration(
color: warningColor,
borderRadius:
BorderRadius.circular(5),
),
child: Text(
'disagree',
style: primaryColor600Style
.copyWith(
fontSize: fontSize9,
color: Colors.white,
),
).tr(),
),
)
]),
),
),
),
if(solversStatus[solver] != null && (povStatus != 'pic' && povStatus != 'pic-client'))
Container(
padding: EdgeInsets.all(5),
decoration: BoxDecoration(
color: formBackgroundColor,
borderRadius: BorderRadius.all(
Radius.circular(10))),
child: Text(
solversStatus[solver],
style: weight600Style.copyWith(
color: primaryColor,
fontSize: 9,
),
),
),
],
),
);
use Text overflow
Text(
'You have pushed the button this many times:dfjhejh dskfjkawejfkjadshfkljhaskdfhekjnkjvnkjasdklfjjekjlkj',
maxLines: 1,
overflow: TextOverflow.ellipsis,
)
or You can use https://pub.dev/packages/marquee package, it will scroll your text infinitly. make sure to wrap this marquee widget in a sizedbox with height and width defined.

flutter Problem same quantity show on products

when I am increasing my quantity of one product then all product's quantity is increasing, so how to solve it.
This is my product page:
import 'dart:convert';
import 'package:carousel_pro/carousel_pro.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:hospital/Authentication/LoginLogoutScreenPage/login.dart';
import 'package:hospital/CartPage/Cart_Api/cart_api.dart';
import 'package:hospital/CartPage/pages/cartPage.dart';
import 'package:hospital/Drawer/dropdown_menu.dart';
import 'package:hospital/ProductDetailsPage/product_detailPage.dart';
import 'package:hospital/ProductDetailsPage/related_product_page.dart';
import 'package:hospital/SecondSection/Medicine/medicine_page.dart';
import 'package:hospital/constant.dart';
import 'package:hospital/customApiVariable.dart';
import 'package:http/http.dart' as http;
import 'package:line_icons/line_icons.dart';
import 'package:provider/provider.dart';
class DetailPage extends StatefulWidget {
final plistId;
const DetailPage({Key key, this.plistId}) : super(key: key);
#override
_DetailPageState createState() => _DetailPageState();
}
class _DetailPageState extends State<DetailPage> {
final GlobalKey<FormState> _formKey = GlobalKey();
int quantity = 1;
var response;
var detailPageApi;
#override
void initState() {
super.initState();
fetchData(widget.plistId);
}
fetchData(var consultWithDoctor) async {
var api = Uri.parse(
'$ecommerceBaseUrl/productListApi.php?a2rTokenKey=$a2rTokenKey&plistId=${widget.plistId}');
response = await http.get(
api,
);
print("detailPageApi " + api.toString());
print("detailPageBody " + response.body);
detailPageApi = jsonDecode(response.body);
print("detailPagelist " + detailPageApi.toString());
setState(() {});
}
Future _submit() async {
var errorMessage = 'Authentication Failed';
if (successfully_add_cart_status.toString() == 'false') {
errorMessage = 'Please try again later';
print(errorMessage);
_showerrorDialog(errorMessage);
} else {
errorMessage = 'Product Succesfully Added to Cart';
print(errorMessage);
_showerrorDialog(errorMessage);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: kGreen,
title: Text(
"Details",
style: TextStyle(fontStyle: FontStyle.italic),
),
actions: [
IconButton(
icon: Icon(Icons.shopping_cart),
// onPressed: () => print("open cart"),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Cartpage()),
);
},
),
DropDownMenu(),
],
),
body: Container(
child: response != null
? ListView.builder(
itemCount: detailPageApi.length.clamp(0, 1),
scrollDirection: Axis.vertical,
physics: ScrollPhysics(),
shrinkWrap: true,
itemBuilder: (context, index) {
var details = detailPageApi[index];
if (details['num'] == 0) {
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.white,
),
);
}
return Column(
children: <Widget>[
Hero(
tag: "1",
child: SizedBox(
height: 300.0,
width: 300.0,
child: Carousel(
boxFit: BoxFit.cover,
autoplay: false,
animationCurve: Curves.fastOutSlowIn,
animationDuration: Duration(milliseconds: 800),
dotSize: 6.0,
dotIncreasedColor: Colors.black,
dotBgColor: Colors.transparent,
// dotPosition: DotPosition.topRight,
dotVerticalPadding: 10.0,
showIndicator: true,
indicatorBgPadding: 7.0,
images: [
NetworkImage(details['pImgImg']),
],
),
),
),
SizedBox(
height: 50,
),
Padding(
padding: const EdgeInsets.only(left: 20, right: 20),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"Name :",
style: TextStyle(
fontSize: 18,
height: 1.5,
fontWeight: FontWeight.w500),
),
SizedBox(
width: 20,
),
Flexible(
child: Text(
// widget.details,
details['productName'],
style: TextStyle(
fontSize: 17,
height: 1.5,
fontWeight: FontWeight.w500),
),
),
],
),
),
SizedBox(
height: 20,
),
Padding(
padding: const EdgeInsets.only(left: 20, right: 20),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"Details :",
style: TextStyle(
fontSize: 18,
height: 1.5,
fontWeight: FontWeight.w500),
),
SizedBox(
width: 20,
),
Flexible(
child: Text(
// widget.details,
details['productDescription'],
style: TextStyle(
fontSize: 17,
height: 1.5,
fontWeight: FontWeight.w500),
),
),
],
),
),
SizedBox(
height: 20,
),
Padding(
padding: const EdgeInsets.only(left: 20, right: 20),
child: Row(
children: <Widget>[
Text(
"Price :",
style: TextStyle(
fontSize: 18, fontWeight: FontWeight.w500),
),
SizedBox(
width: 20,
),
Row(
children: <Widget>[
Text(
// "Rs " + widget.pPromotionPrice,
"Rs 55.0",
style: TextStyle(
fontSize: 17,
fontWeight: FontWeight.w500),
),
SizedBox(
width: 20,
),
Text(
// "Rs " + widget.pPrice,
"Rs 100",
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w500,
// color: warning,
decoration: TextDecoration.lineThrough),
)
],
)
],
),
),
SizedBox(
height: 25,
),
Padding(
padding: const EdgeInsets.only(right: 20, left: 20),
child: Row(
children: <Widget>[
Text(
"Qty :",
style: TextStyle(
fontSize: 17, fontWeight: FontWeight.w500),
),
SizedBox(
width: 20,
),
Row(
children: <Widget>[
InkWell(
onTap: () {
if (quantity > 1) {
setState(() {
quantity = --quantity;
});
}
// minus here
},
child: Container(
width: 25,
height: 25,
decoration: BoxDecoration(
// border: Border.all(color: primary),
shape: BoxShape.circle),
child: Icon(
LineIcons.minus,
size: 15,
),
),
),
SizedBox(
width: 15,
),
Text(
quantity.toString(),
style: TextStyle(fontSize: 16),
),
SizedBox(
width: 15,
),
InkWell(
onTap: () {
setState(() {
quantity = ++quantity;
});
// minus here
},
child: Container(
width: 25,
height: 25,
decoration: BoxDecoration(
// border: Border.all(color: primary),
shape: BoxShape.circle),
child: Icon(
LineIcons.plus,
size: 15,
),
),
),
],
)
],
),
),
SizedBox(
height: 50,
),
InkWell(
onTap: () async {
if (var_uid.toString() != null.toString()) {
_submit();
var qty = quantity.toString();
var plistId = widget.plistId;
print('pplistid' + plistId);
var uid = var_uid.toString();
var sid = var_sid.toString();
print('uuid' + uid);
print('ssid' + sid);
var response =
await add_to_cart_fn(qty, plistId, uid, sid);
print("rsp: " + response['msg']);
} else {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => LoginPage()));
}
},
// },
child: Padding(
padding: EdgeInsets.only(left: 20, right: 20),
child: Container(
height: 45,
width: double.infinity,
decoration: BoxDecoration(
color: kGreen,
borderRadius: BorderRadius.circular(30)),
child: Center(
child: Text(
"ADD TO CART",
style: TextStyle(
color: kWhite,
fontSize: 20,
),
),
),
),
),
),
SizedBox(height: 20.0),
RelatedProductPage(plistId: widget.plistId)
],
);
})
: Center(
child: CircularProgressIndicator(
backgroundColor: Colors.white,
),
),
),
);
}
void _showerrorDialog(String message) {
Fluttertoast.showToast(
msg: message,
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.grey[350],
textColor: Colors.black,
fontSize: 16.0);
}
}
You are using the same quantity variable against each item. Changing the value on one of those will cause all items to update. What you need to do is to keep a Map of quantity selected against product id. That way whenever you increase or decrease the quantity, you update the quantity against that specific product id and the rest will remain unchanged.
EDIT: Here is how this will work
//Create a new map to save the product id and product selected quantity
var productQuantity = new Map<int, int>()
//When setting the values of the product, set the quantity from the map
Padding(
padding: const EdgeInsets.only(right: 20, left: 20),
child: Row(
children: <Widget>[
Text(
"Qty :",
style: TextStyle(
fontSize: 17, fontWeight: FontWeight.w500),
),
SizedBox(width: 20,),
Row(
children: <Widget>[
InkWell(
onTap: () {
if (quantity > 1) {
setState(() {
//Changed here
productQuantity['$productId'] -= 1;
});
}
},
child: Container(
width: 25,
height: 25,
decoration: BoxDecoration(shape: BoxShape.circle),
child: Icon(
LineIcons.minus,
size: 15,
),
),
),
SizedBox(width: 15,),
Text(
//Changed here
productQuantity['$productId'].toString(),
style: TextStyle(fontSize: 16),
),
SizedBox(width: 15,),
InkWell(
onTap: () {
setState(() {
//Changed here
productQuantity['$productId'] += 1;
});
},
child: Container(
width: 25,
height: 25,
decoration: BoxDecoration(
shape: BoxShape.circle),
),
child: Icon(
LineIcons.plus,
size: 15,
),
),
),
],
)
],
),
)
you set the common quantity in all products so change it and set it inside the class.
Please Check the example
import 'package:flutter/material.dart';
class QuantityUpdatePage extends StatefulWidget {
#override
_QuantityUpdatePageState createState() => _QuantityUpdatePageState();
}
class _QuantityUpdatePageState extends State<QuantityUpdatePage> {
List<Product> productArray = [];
#override
void initState() {
super.initState();
WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
productArray.clear();
productArray.add(Product(1, "Product 1", 1));
productArray.add(Product(2, "Product 2", 1));
productArray.add(Product(3, "Product 3", 1));
productArray.add(Product(4, "Product 4", 1));
productArray.add(Product(5, "Product 5", 1));
setState(() {});
});
}
#override
void dispose() {
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("QUANTITY UPDATE")),
body: ListView.builder(
shrinkWrap: true,
itemCount: productArray.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.only(right: 20, left: 20),
child: ListView(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
children: [
SizedBox(
height: 20,
),
Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(productArray[index].productName),
SizedBox(
width: 40,
),
Row(
children: <Widget>[
Text(
"Qty :",
style: TextStyle(fontSize: 17, fontWeight: FontWeight.w500),
),
SizedBox(
width: 20,
),
Row(
children: <Widget>[
InkWell(
onTap: () {
if (productArray[index].quantity > 1) {
setState(() {
productArray[index].quantity = --productArray[index].quantity;
});
}
// minus here
},
child: Container(
width: 25,
height: 25,
decoration: BoxDecoration(
// border: Border.all(color: primary),
shape: BoxShape.circle),
child: Icon(
Icons.minimize,
size: 15,
),
),
),
SizedBox(
width: 15,
),
Text(
productArray[index].quantity.toString(),
style: TextStyle(fontSize: 16),
),
SizedBox(
width: 15,
),
InkWell(
onTap: () {
setState(() {
productArray[index].quantity = ++productArray[index].quantity;
});
// minus here
},
child: Container(
width: 25,
height: 25,
decoration: BoxDecoration(
// border: Border.all(color: primary),
shape: BoxShape.circle),
child: Icon(
Icons.add,
size: 15,
),
),
),
],
)
],
),
],
),
SizedBox(
height: 20,
),
],
),
);
}));
}
}
class Product {
String productName;
int quantity;
int id;
Product(this.id, this.productName, this.quantity);
}
#Deepak if you don't understand Maps use list instead, with a value being updated for each index. Initialize a list of int types with some large values like 1000000, and update the value for each index. use ListView builder to fetch the data from the API for each index.
List<int> quantity = List.empty(growable: true);
OR
List<int> quantity = List.filled(10000, []);
For updating quantity:-
quantity[index] += 1;
For Grid view thing, refer this example from CodeGrepper:-
GridView.count(
// Create a grid with 2 columns. If you change the scrollDirection to
// horizontal, this produces 2 rows.
crossAxisCount: 2,
// Generate 100 widgets that display their index in the List.
children: List.generate(100, (index) {
return Center(
child: Text(
'Item $index',
style: Theme.of(context).textTheme.headline5,
),
);
}),
);

Having difficulty adding items to shopping cart - Flutter

I have my Cart model as below
class Cart {
String description;
double unitCost;
double amount;
int quantity;
String color;
String imageURl;
Cart({
this.description,
this.unitCost,
this.amount,
this.color,
this.quantity,
this.imageURl,
});
}
And my CartData notifier class which has a _cartList with pre-loaded data as shown below:
class CartData extends ChangeNotifier {
List<Cart> _cartItems = [
Cart(
imageURl:
'https://s2.r29static.com/bin/entry/ebd/0,675,2000,1050/x,80/1929471/image.jpg',
description: 'Nike Air Max',
quantity: 3,
unitCost: 6000,
),
Cart(
color: 'red',
description: 'Nike Air Max',
quantity: 3,
unitCost: 3000,
),
Cart(
imageURl:
'https://s2.r29static.com/bin/entry/ebd/0,675,2000,1050/x,80/1929471/image.jpg',
description: 'Nike Air Max',
quantity: 6,
unitCost: 6000,
),
Cart(
color: 'purple',
description: 'Nike Air Max',
quantity: 2,
unitCost: 1000,
),
Cart(
color: 'purple',
description: 'Nike Air Max',
quantity: 2,
unitCost: 2000,
),
];
UnmodifiableListView<Cart> get cartItems {
return UnmodifiableListView(_cartItems);
}
int get cartItemsCount {
return _cartItems.length;
}
void addItemToCart(
String color,
double unitCost,
String description,
String imageURL,
int quantity,
) {
_cartItems.insert(
0,
Cart(
color: color,
unitCost: unitCost,
description: description,
imageURl: imageURL,
quantity: quantity,
),
);
notifyListeners();
}
void getTotalSum(Cart cart) {}
double getAmount(int qty, double unitCost) {
return qty * unitCost;
}
void upDateCartItem(Cart cartItem, bool isIncrementing) {
if (isIncrementing == true) {
cartItem.quantity++;
print(
'Cart item purchase quantity is: ${cartItem.quantity}, after incrementing from updateCartItem');
} else {
if (cartItem.quantity >= 1) {
cartItem.quantity--;
print(
'Cart item purchase quantity is: ${cartItem.quantity} after decrementing from updateCartItem');
}
if (cartItem.quantity == 0) {
deleteItemFromCart(cartItem);
}
print(cartItem.quantity);
}
cartItem.amount = cartItem.quantity * cartItem.unitCost;
print('Cart Item amount is: ${cartItem.amount} from updateCartItem');
notifyListeners();
}
void deleteItemFromCart(Cart cartItem) {
_cartItems.remove(cartItem);
notifyListeners();
}
}
I want to be able to add items on the fly to my existing list of Cart Items using my addItemToCart() method, and display them immediately on my shopping cart page.
In my shopping screen, I have a few declarations as below:
String defaultDescription = 'add description';
String paymentDescription = 'add description';
String amount = '0';
int cartTotal = 0;
However, I'm unable to add item(s) to cart from my shopping screen when I call the addItemToCart method as below:
_addToCart() {
if (amount == '' || amount == '0') {
print('add an amount');
_showToast(this.context, 'amount');
} else if (paymentDescription == defaultDescription) {
print('please enter a valid description to proceed');
_showToast(this.context, 'payment description');
} else {
print(amount);
print(paymentDescription);
//do something like add to cart
CartData cartData = Provider.of<CartData>(context, listen: false);
cartData.addItemToCart(
null,
double.parse(output),
paymentDescription,
null,
1,
);
}
setState(() {
paymentDescription = defaultDescription;
amount = '0';
});
}
Here's my checkout screen that displays the cart Items:
class CheckoutScreen extends StatefulWidget {
static const String id = 'checkout_screen';
#override
_CheckoutScreenState createState() => _CheckoutScreenState();
}
class _CheckoutScreenState extends State<CheckoutScreen> {
#override
void initState() {
super.initState();
CustomerNotifier customerNotifier =
Provider.of<CustomerNotifier>(context, listen: false);
customerNotifier.getCustomers(customerNotifier);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: ChangeNotifierProvider(
create: (context) => CartData(),
child: Consumer<CartData>(
builder: (context, cartData, child) {
return Column(
children: <Widget>[
Row(
children: <Widget>[
IconButton(
icon: Icon(
Icons.arrow_back_ios,
color: Colors.black26,
),
onPressed: () => Navigator.pop(context),
),
Text(
'Shopping cart',
style: TextStyle(
fontSize: 21.0,
color: Colors.black26,
fontWeight: FontWeight.bold,
),
),
],
),
Container(
margin: EdgeInsets.only(top: 8.0, bottom: 8.0),
height: MediaQuery.of(context).size.height / 16,
width: MediaQuery.of(context).size.width - 150,
decoration: BoxDecoration(
border: Border.all(color: kThemeStyleButtonFillColour),
borderRadius: BorderRadius.circular(5.0),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Customer drop down',
textAlign: TextAlign.center,
style: kRegularTextStyle,
maxLines: 2,
textDirection: TextDirection.ltr,
softWrap: true,
),
SizedBox(width: 5.0),
Icon(
Icons.keyboard_arrow_down,
color: kThemeStyleButtonFillColour,
size: 25,
),
],
),
),
Expanded(
flex: 4,
child: Container(
height: MediaQuery.of(context).size.height - 225,
padding: const EdgeInsets.only(
left: 16, right: 16, bottom: 8.0),
child: ListView.builder(
itemCount: cartData.cartItems.length,
shrinkWrap: true,
itemBuilder: (context, index) {
final cartItem = cartData.cartItems[index];
return cartData.cartItems.isEmpty
? Container(
child: Align(
alignment: Alignment.center,
child: Text('Your cart is empty')))
: Container(
color: Colors.white,
margin: EdgeInsets.symmetric(vertical: 6.0),
child: Row(
children: <Widget>[
Expanded(
child: Container(
width: 80.0,
height: 70.0,
child: Center(
child: cartItem.imageURl == null
? Container(
padding:
EdgeInsets.all(4.0),
decoration: BoxDecoration(
color: Color((math.Random()
.nextDouble() *
0xFFFFFF)
.toInt())
.withOpacity(1.0),
borderRadius:
BorderRadius.circular(
20.0),
),
)
: Container(
padding:
EdgeInsets.all(4.0),
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(
cartItem.imageURl),
),
borderRadius:
BorderRadius.circular(
20.0),
),
),
),
),
),
SizedBox(width: 12.0),
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
Container(
width: 100.0,
child: Text(
cartItem.description,
style: TextStyle(
fontWeight: FontWeight.bold),
),
),
SizedBox(height: 8.0),
Row(
children: <Widget>[
GestureDetector(
child: Container(
width: 20.0,
height: 20.0,
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius:
BorderRadiusDirectional
.circular(4.0),
),
child: Icon(
Icons.remove,
color: Colors.white,
size: 15.0,
),
),
onTap: () {
cartData.upDateCartItem(
cartItem, false);
},
),
Padding(
padding:
const EdgeInsets.symmetric(
horizontal: 15.0),
child: Text(
'${cartItem.quantity}',
style: TextStyle(
fontWeight:
FontWeight.bold,
fontSize: 15.0),
),
),
GestureDetector(
child: Container(
width: 20.0,
height: 20.0,
decoration: BoxDecoration(
color:
kThemeStyleButtonFillColour,
borderRadius:
BorderRadiusDirectional
.circular(4.0),
),
child: Icon(
Icons.add,
color: Colors.white,
size: 15.0,
),
),
onTap: () {
cartData.upDateCartItem(
cartItem, true);
},
),
],
),
],
),
// Spacer(),
Expanded(
child: Text(
'${cartData.getAmount(cartItem.quantity, cartItem.unitCost)}',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15.0),
),
),
Expanded(
child: GestureDetector(
child: Icon(
Icons.delete_forever,
size: 25.0,
color: kThemeStyleButtonFillColour,
),
onTap: () => cartData
.deleteItemFromCart(cartItem),
),
),
],
),
);
},
),
),
),
],
);
},
),
),
),
);
}
}
What could I be missing here?
Calling your addItemToCart() should rebuild the children inside Consumer<CartData>() because of notifyListeners(). This should help you give some clue on what's happening.
Add a debugPrint('List length: ${cartData.cartItemsCount}') inside the Consumer to check if List _cartItems changes after adding an item.

trying to add to bag and to update prices and cups

I am trying to do this test TODOs: but i have been have issuses pls help: i am trying to Uncomment the _confirmOrderModalBottomSheet() method to show summary of order, Uncomment the setState() function to clear the price and cups, and Change the 'price' to 0 when this button is clicked Increment the _cupsCounter when 'Add to Bag' button is clicked, and to Call setState((){}) method to update both price and cups counter when 'Add to Bag' button is clicked
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Coffee Test',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Colors.white,
),
home: MyHomePage(title: 'Coffee Test'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _selectedPosition = -1;
String _coffeePrice ="0";
int _cupsCounter =0;
int price = 0;
String _currency ="₦";
static const String coffeeCup ="images/coffee_cup_size.png";
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0,
title: FlatButton(
onPressed: (){
//TODO: Uncomment the _confirmOrderModalBottomSheet() method to show summary of order
//_confirmOrderModalBottomSheet(totalPrice: "$_currency$price", numOfCups: "x $_cupsCounter");
},
child: Text("Buy Now",style: TextStyle(color: Colors.black87),),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(18.0), side: BorderSide(color: Colors.blue))
),
actions: [
InkWell(
onTap: () {
//TODO: Uncomment the setState() function to clear the price and cups
//TODO: Change the 'price' to 0 when this button is clicked
setState(() {
this.price = -1;
this._cupsCounter = 0;
});
Icon(Icons.clear);
}),
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Container(
height: double.maxFinite,
alignment: Alignment.center,
child: Text("$_cupsCounter Cups = $_currency$price.00", style: TextStyle(fontSize: 18),),
),
)
],
),
body: Padding(padding: EdgeInsets.all(20), child: _mainBody(),) // This trailing comma makes auto-formatting nicer for build methods.
);
}
Widget _mainBody(){
return SingleChildScrollView(
child: Container(
height: double.maxFinite,
width: double.maxFinite,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
flex: 0,
child: Stack(
children: [
Container(
width: double.maxFinite,
height: 250,
margin: EdgeInsets.only(left: 50, right: 50, bottom: 50, top: 60),
decoration: BoxDecoration(borderRadius:
BorderRadius.all(Radius.circular(180)),
color: Color.fromRGBO(239, 235, 233, 100)),
),
Container(
alignment: Alignment.center,
width: double.maxFinite,
height: 350,
child: Image.asset("images/cup_of_coffee.png", height: 300,),
)
],
)),
Padding(padding: EdgeInsets.all(10),),
Expanded(flex: 0,child: Text("Caffè Americano",
style: TextStyle(fontWeight: FontWeight.bold,
fontSize: 30),)),
Padding(padding: EdgeInsets.all(6),),
Expanded(flex: 0, child: Text("Select the cup size you want and we will deliver it to you in less than 48hours",
style: TextStyle(fontWeight: FontWeight.bold,
fontSize: 14, color: Colors.black45,),
textAlign: TextAlign.start,),
),
Container(
margin: EdgeInsets.only(top: 30, left: 20),
height: 55,
width: double.maxFinite,
alignment: Alignment.center,
child:Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
RichText(text: TextSpan(
text: _currency,
style: TextStyle(fontWeight: FontWeight.bold,
fontSize: 25, color: Colors.black87),
children: [
TextSpan(text: _coffeePrice, style: TextStyle(fontSize: 50, fontWeight: FontWeight.bold))
]
),),
Padding(
padding: EdgeInsets.only(right: 15),
),
ListView.builder(itemBuilder: (context, index){
return InkWell(
child: _coffeeSizeButton(_selectedPosition == index,
index ==0? "S" : index ==1? "M": "L"),
onTap: (){
setState(() {
this._coffeePrice= index ==0? "300" : index ==1? "600": "900";
_selectedPosition = index;
});
},
);
}, scrollDirection: Axis.horizontal,
itemCount: 3, shrinkWrap: true,),
],),
),
Container(
margin: EdgeInsets.only(top: 30),
padding: EdgeInsets.all(10),
width: double.maxFinite,
height: 70,
child: FlatButton(onPressed: (){
//TODO: Currently _cupsCounter only show 1 when this button is clicked.
// TODO: Increment the _cupsCounter when 'Add to Bag' button is clicked'
//TODO: Call setState((){}) method to update both price and cups counter when 'Add to Bag' button is clicked
this._cupsCounter = 1;
this.price += int.parse(_coffeePrice);
}, child: Center(child: Text("Add to Bag",
style: TextStyle(fontWeight: FontWeight.bold, color: Colors.white),)
,),
color: Colors.blue,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50)
),
),
)
],
),
),
);
}
Widget _coffeeSizeButton(bool isSelected, String coffeeSize){
return Stack(
children: [
Container(alignment: Alignment.center, width: 55,
child: Text(coffeeSize, style: TextStyle(fontSize: 10, fontWeight: FontWeight.bold,
color: isSelected? Colors.blue: Colors.black45),),),
new Container(
margin: EdgeInsets.only(right: 10),
child: Image.asset(coffeeCup, width:50, color: isSelected ? Colors.blue: Colors.black45,),
decoration: BoxDecoration(border: Border(top: BorderSide(color: isSelected? Colors.blue: Colors.black45,
width: isSelected? 2: 1), left: BorderSide(color: isSelected? Colors.blue: Colors.black45,
width: isSelected? 2: 1), bottom: BorderSide(color: isSelected? Colors.blue: Colors.black45,
width: isSelected? 2: 1), right: BorderSide(color: isSelected ?Colors.blue: Colors.black45 ,
width: isSelected? 2: 1)), borderRadius: BorderRadius.all(Radius.circular(5))),
)
],
);
}
void _confirmOrderModalBottomSheet({String totalPrice, String numOfCups}){
showModalBottomSheet(
context: context,
builder: (builder){
return new Container(
height: 150.0,
color: Colors.transparent, //could change this to Color(0xFF737373),
//so you don't have to change MaterialApp canvasColor
child: new Container(
padding: EdgeInsets.all(10),
decoration: new BoxDecoration(
color: Colors.white,
borderRadius: new BorderRadius.only(
topLeft: const Radius.circular(10.0),
topRight: const Radius.circular(10.0))),
child: Column(
children: [
Container(
child: Text("Confirm Order",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18),),
alignment: Alignment.center, height: 30, decoration: BoxDecoration(
), ),
_getEstimate(totalPrice, numOfCups)
],
)),
);
}
);
}
Widget _getEstimate(String totalPrice, String numOfCups){
return Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Image.asset("images/cup_of_coffee.png", height: 70, width: 50,),
Padding(padding: EdgeInsets.all(10)),
Text(numOfCups, style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),),
Padding(padding: EdgeInsets.all(10)),
Text(totalPrice, style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),)
],
);
}
}
You're setting 1 to your _cupsCounter instead of adding one to it.
When updating your values, putting the operation i.e _cupsCounter += 1; in setState will update the state of your widget which makes values change in your widgets.
setState((){
_cupsCounter += 1; // make it +=1 instead of =1.
price += int.parse(_coffeePrice);
});
Also you can use setState by putting it after your operation which will update the state of your widget after the operation is done.
_cupsCounter += 1; // make it +=1 instead of =1.
price += int.parse(_coffeePrice);
setState((){});
Full code should look like this.
Container(
margin: EdgeInsets.only(top: 30),
padding: EdgeInsets.all(10),
width: double.maxFinite,
height: 70,
child: FlatButton(onPressed: (){
// Currently _cupsCounter only show 1 when this button is clicked.
// Increment the _cupsCounter when 'Add to Bag' button is clicked'
// Call setState((){}) method to update both price and cups counter when 'Add to Bag' button is clicked
setState((){
_cupsCounter += 1; // make it +=1 instead of =1.
price += int.parse(_coffeePrice);
}); // call setState like this
}, child: Center(child: Text("Add to Bag",
style: TextStyle(fontWeight: FontWeight.bold, color: Colors.white),)
,),
color: Colors.blue,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50)
),
),
)

Flutter, calculated Double do not work for circularprogress bar

I want to calculate the Percentage for the different Circularprogressbars with data from my Firestore Database. But when i use the calculated Doubles instead of hardcoded doubles i get this error and i can not explain my self why iam getting this error in the Terminal:
|
The getter 'weekActivity' was called on null.
Receiver: null
Tried calling: weekActivity
|
Can someone help me to fix this error?
Error Message
import 'dart:core';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_circular_chart/flutter_circular_chart.dart';
import 'package:testapp/models/Goals.dart';
import 'package:testapp/services/Services.dart';
class ReadingPage extends StatefulWidget {
final Goal goal;
const ReadingPage({Key key, this.goal}) : super(key: key);
#override
_ReadingPageState createState() => _ReadingPageState();
}
class _ReadingPageState extends State<ReadingPage> {
int _currentValue = 1;
//weeklyGoals
bool weekActivityFinished = false;
bool weekReadTimeFinished = false;
#override
Widget build(BuildContext context) {
final _chartSize = const Size(145, 145);
return Scaffold(
resizeToAvoidBottomPadding: false,
appBar: PreferredSize(
preferredSize: Size.fromHeight(35),
child: AppBar(
title: Align(
alignment: Alignment.center,
child: Text('Reading', style: TextStyle(
fontWeight: FontWeight.w500,
color: Colors.grey[900],
fontSize: 25,
decoration: TextDecoration.underline,
decorationColor: Color(0XFF006699),
decorationThickness: 1.5,
),),
),
backgroundColor: Colors.white,
),
),
body: Container(
margin: EdgeInsets.symmetric(vertical: 0),
height: 260.0,
child: StreamBuilder(
stream: FirestoreService().getGoals(),
builder: (BuildContext context,
AsyncSnapshot<List<Goal>> snapshot) {
if (snapshot.hasError || !snapshot.hasData)
return Center(child: CircularProgressIndicator(
backgroundColor: Color(0XFF1954A1),
));
return SizedBox(
height: 250,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 1,
itemBuilder: (BuildContext context, int index) {
Goal goal = snapshot.data[index];
return Row(
children: <Widget>[
Container(
padding: EdgeInsets.only(
top: 5, bottom: 10, left: 30, right: 30),
child: Container(
width: 330.0,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(20.0)),boxShadow: [
BoxShadow(
color: Colors.grey[500],
offset: const Offset(0.5, 1),
blurRadius: 5.0,
spreadRadius: 0.1,
),
]),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Container(
padding: EdgeInsets.only(left: 20),
width: 240,
child: Align(
alignment: Alignment.topLeft,
child: Container(
child: Text(
'WeeklyGoals', style: TextStyle(
fontSize: 25,
),),
),
),
),
Align(
alignment: Alignment.topRight,
child: Container(
padding: EdgeInsets.only(top: 5,right: 0, left: 0,
bottom: 0),
child: FlatButton(
child: Text('edit', style: TextStyle(
fontSize: 16,
color: Colors.yellow[700]
),),
onPressed: () {}
)
),
)
],
),
Row(
children: <Widget>[
Container(
width: 160,
margin: EdgeInsets.only(right: 10),
child: Column(
children: <Widget>[
Text('Activity', style: TextStyle(
fontSize: 18
),),
Center(
child: new AnimatedCircularChart(
size: _chartSize,
initialChartData: <
CircularStackEntry>[
new CircularStackEntry(
<CircularSegmentEntry>[
new CircularSegmentEntry(
_weekActivityProgress(),
weekActivityFinished
? Colors
.yellow[700]
: Color(
0XFF006699),
rankKey: 'completed',
),
new CircularSegmentEntry(
100,
Colors.grey[300],
rankKey: 'remaining',
),
],
rankKey: 'progress',
),
],
chartType: CircularChartType
.Radial,
percentageValues: true,
holeLabel: '${goal
.weekActivity != null
? goal.weekActivity
: '-'}/${goal
.weekActivityGoal != null
? goal.weekActivityGoal
: '-'}',
labelStyle: new TextStyle(
color: Colors.blueGrey[600],
fontWeight: FontWeight.bold,
fontSize: 24.0,
),
),
),
],
),
),
Container(
width: 160,
child: Column(
children: <Widget>[
Text('Time', style: TextStyle(
fontSize: 18
),),
Center(
child: new AnimatedCircularChart(
size: _chartSize,
initialChartData: <
CircularStackEntry>[
new CircularStackEntry(
<CircularSegmentEntry>[
new CircularSegmentEntry(
_weekReadingProgress(),
weekReadTimeFinished
? Colors
.yellow[700]
: Color(
0XFF006699),
rankKey: 'completed',
),
new CircularSegmentEntry(
100,
Colors.grey[300],
rankKey: 'remaining',
),
],
rankKey: 'progress',
),
],
chartType: CircularChartType
.Radial,
percentageValues: true,
holeLabel: '${goal
.weekReadTime != null
? goal.weekReadTime
.toStringAsFixed(2)
: '-'} / ${goal
.weekReadTimeGoal != null
? goal.weekReadTimeGoal
: '-'}',
labelStyle: new TextStyle(
color: Colors.blueGrey[600],
fontWeight: FontWeight.bold,
fontSize: 24.0,
),
),
),
],
),
),
],
),
],
),
),
),
]);
}),
);
})));
}
//week
double _weekReadingProgress(){
var _weekReadingProgress = widget.goal.weekReadTime != null? widget.goal.weekReadTimeGoal : 0 *100 ~/
widget.goal.weekReadTimeGoal;
if(widget.goal.weekReadTime.toInt() >= widget.goal.weekReadTimeGoal){
setState(() {
weekReadTimeFinished = true;
});}
return _weekReadingProgress.toDouble();
}
double _weekActivityProgress(){
var _weekActivityProgress = widget.goal.weekActivity != null? widget.goal.weekActivity : 0 *100 ~/
widget.goal.weekActivityGoal;
if(widget.goal.weekActivity >= widget.goal.weekActivityGoal){
setState(() {
weekReadTimeFinished = true;
});}
return _weekActivityProgress.toDouble();
}}
The variable goal is null at one of places where you use goal.weekActivity.
At all places where you use goal.weekActivity, first ensure goal != null. Since it comes from Firestore, it's possible that there are no goals in the database when this error occurs. If you try this and find that it is always null, you should make sure it exists in the database.