Unable to add elements to a List in Flutter - flutter
Issue:
I am trying to add items to wishlist and cart on pressing relevant icons of an instrument item card. However, when I tap on them, neither are they getting added to the global lists of wishList and cartList, nor are the wishList and cart icons changing colors to red and blue respectively.
Below are my codes for the relevant .dart files.
home_welcome_screen.dart - The screen which hosts the instrument item cards in a horizontal ListView:
import 'package:flutter/material.dart';
import 'package:musicart/screens/instrument_detail.dart';
import 'package:musicart/screens/wishlist_screen.dart';
import 'package:musicart/widgets/animated_bottom_bar.dart';
import 'package:musicart/widgets/brand_logo_card.dart';
import 'package:musicart/widgets/instrument_card.dart';
import 'package:musicart/widgets/search_widget.dart';
import 'package:musicart/widgets/text_label.dart';
import '../global_variables/global_variables.dart';
import 'package:carousel_slider/carousel_slider.dart';
class HomeWelcomeScreen extends StatefulWidget {
const HomeWelcomeScreen({Key? key}) : super(key: key);
#override
State<HomeWelcomeScreen> createState() => _HomeWelcomeScreenState();
}
class _HomeWelcomeScreenState extends State<HomeWelcomeScreen> {
final TextEditingController _searchBoxController = TextEditingController();
final String _hintText = "Search instruments...";
int _currentIndex = 0;
int _currentCarouselIndex = 0;
#override
Widget build(BuildContext context) {
double? screenWidth = MediaQuery.of(context).size.width;
double? screenHeight = MediaQuery.of(context).size.height;
List<Widget> indicators(imagesLength, currentIndex) {
return List<Widget>.generate(imagesLength, (index) {
return Container(
margin: EdgeInsets.symmetric(
vertical: screenHeight * 0.01,
horizontal: 2,
),
width: currentIndex == index ? 15 : 10,
height: 3,
decoration: BoxDecoration(
color: currentIndex == index ? Colors.black87 : Colors.grey,
borderRadius: const BorderRadius.all(
Radius.circular(2),
),
),
);
});
}
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(top: screenHeight * 0.02),
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(
left: screenWidth * 0.025, right: screenWidth * 0.19),
child: Image(
image: const AssetImage("../assets/images/logo.png"),
height: 40,
width: screenWidth * 0.25,
),
),
Padding(
padding: EdgeInsets.only(right: screenWidth * 0.025),
child: SearchWidget(
width: screenWidth * 0.3,
onChanged: (p0) {},
searchController: _searchBoxController,
onTap: () {},
hintText: _hintText,
),
),
Padding(
padding: EdgeInsets.only(right: screenWidth * 0.025),
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
WishListScreen(mywishList: wishList[0])));
},
child: const Icon(
Icons.favorite_outline_rounded,
color: Colors.black87,
size: 40,
),
),
),
Padding(
padding: EdgeInsets.only(right: screenWidth * 0.025),
child: InkWell(
onTap: () {},
child: const Icon(
Icons.shopping_cart_outlined,
color: Colors.black87,
size: 40,
),
),
),
],
),
Padding(
padding: EdgeInsets.only(top: screenHeight * 0.015),
),
SizedBox(
width: screenWidth,
height: screenHeight,
child: Column(
children: [
Expanded(
child: ListView(
children: [
// Padding(
// padding: EdgeInsets.only(top: screenHeight * 0.01)),
CarouselSlider(
items: carouselImageList.map<Widget>((i) {
return Builder(
builder: (BuildContext context) {
return Container(
width: screenWidth * 0.95,
decoration: BoxDecoration(
image:
DecorationImage(image: NetworkImage(i)),
),
);
},
);
}).toList(),
options: CarouselOptions(
height: screenHeight * 0.25,
aspectRatio: 16 / 9,
autoPlay: true,
autoPlayInterval: const Duration(seconds: 5),
initialPage: 0,
viewportFraction: 1,
onPageChanged: (index, timed) {
setState(() {
_currentCarouselIndex = index;
});
}),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: indicators(
carouselImageList.length, _currentCarouselIndex),
),
Padding(
padding: EdgeInsets.only(
left: screenWidth * 0.025,
top: screenHeight * 0.005,
),
child: TextLabel(
width: screenWidth * 0.15,
labelText: "Top Brands",
),
),
Padding(
padding: EdgeInsets.only(
left: screenWidth * 0.025,
top: screenWidth * 0.025),
),
Padding(
padding: EdgeInsets.symmetric(
horizontal: screenWidth * 0.025),
child: SizedBox(
height: screenHeight * 0.1,
child: Row(
children: [
Expanded(
child: ListView.builder(
itemCount: brandLogos.length,
scrollDirection: Axis.horizontal,
//shrinkWrap: true,
physics:
const AlwaysScrollableScrollPhysics(),
itemBuilder:
(BuildContext context, int index) {
return BrandLogoCard(
width: screenWidth * 0.33,
height: screenHeight * 0.18,
brandImageUrl: brandLogos[index]
["img-url"],
paddingRight: screenWidth * 0.015);
},
),
),
],
),
),
),
Padding(
padding: EdgeInsets.only(
left: screenWidth * 0.025,
top: screenWidth * 0.025),
),
Padding(
padding: EdgeInsets.only(
left: screenWidth * 0.025,
),
child: TextLabel(
width: screenWidth * 0.21,
labelText: "Trending Guitars",
),
),
Padding(
padding: EdgeInsets.only(
left: screenWidth * 0.025,
top: screenWidth * 0.025),
),
Padding(
padding: EdgeInsets.symmetric(
horizontal: screenWidth * 0.025),
child: SizedBox(
height: screenHeight * 0.28,
child: Row(
children: [
Expanded(
child: ListView.builder(
itemCount: instruments.length,
scrollDirection: Axis.horizontal,
//shrinkWrap: true,
physics:
const AlwaysScrollableScrollPhysics(),
itemBuilder:
(BuildContext context, int index) {
return InstrumentCard(
width: screenWidth * 0.4,
height: screenHeight * 0.37,
instrumentImageUrl: instruments[index]
["img-url"],
instrumentName: instruments[index]
["name"],
instrumentMrp:
"₹${instruments[index]["mrp"].toString()}",
instrumentPrice:
"₹${instruments[index]["price"].toString()}",
paddingRight: screenHeight * 0.015,
innerHorizontalSymmetricPadding:
screenWidth * 0.025,
innerVerticalSymmetricPadding:
screenHeight * 0.005,
instrumentDiscount:
"${(((1 - (instruments[index]["price"] / instruments[index]["mrp"])) * 100).round()).toString()}% off",
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
InstrumentDetail(
instrument: instruments[
index])));
},
onWishTap: () {
if (wishList
.contains(instruments[index])) {
setState(() {
wishList.remove(instruments[index]);
});
} else {
setState(() {
wishList.add(instruments[index]);
});
}
},
onCartTap: () {
if (cartList
.contains(instruments[index])) {
setState(() {
cartList.remove(instruments[index]);
});
} else {
setState(() {
cartList.add(instruments[index]);
});
}
},
isWishlisted: (wishList
.contains(instruments[index]))
? true
: false,
isCarted: (cartList
.contains(instruments[index]))
? true
: false,
);
},
),
),
],
),
),
),
Padding(
padding: EdgeInsets.only(
left: screenWidth * 0.025,
top: screenWidth * 0.025),
),
],
),
),
],
),
),
],
),
}
}
instrument_card.dart - The widget for the instrument item displayed on the HomeWelcomeScreen
import 'package:flutter/material.dart';
import 'package:musicart/global_variables/global_variables.dart';
class InstrumentCard extends StatefulWidget {
const InstrumentCard({
Key? key,
required this.width,
required this.height,
required this.instrumentImageUrl,
required this.instrumentName,
required this.instrumentMrp,
required this.instrumentPrice,
required this.paddingRight,
required this.innerHorizontalSymmetricPadding,
required this.innerVerticalSymmetricPadding,
required this.instrumentDiscount,
required this.onTap,
required this.onWishTap,
required this.onCartTap,
required this.isWishlisted,
required this.isCarted,
}) : super(key: key);
final double width;
final double height;
final String instrumentImageUrl;
final String instrumentName;
final String instrumentMrp;
final String instrumentPrice;
final double paddingRight;
final double innerHorizontalSymmetricPadding;
final double innerVerticalSymmetricPadding;
final String instrumentDiscount;
final VoidCallback onTap;
final VoidCallback onWishTap;
final VoidCallback onCartTap;
final bool isWishlisted;
final bool isCarted;
#override
State<InstrumentCard> createState() => _InstrumentCardState();
}
class _InstrumentCardState extends State<InstrumentCard> {
bool isWishlisted = false;
bool isCarted = false;
#override
void initState() {
super.initState();
isWishlisted = widget.isWishlisted;
isCarted = widget.isCarted;
}
#override
Widget build(BuildContext context) {
return InkWell(
onTap: widget.onTap,
child: Padding(
padding: EdgeInsets.only(right: widget.paddingRight),
child: Stack(
children: [
Container(
width: widget.width,
height: widget.height,
decoration: BoxDecoration(
border: Border.all(
color: Colors.grey,
width: 0.5,
),
borderRadius: const BorderRadius.all(
Radius.circular(10),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: widget.width,
height: widget.height * 0.5,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(widget.instrumentImageUrl),
fit: BoxFit.fill,
),
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(10),
topRight: Radius.circular(10),
),
border: Border.all(color: Colors.grey, width: 0.015),
),
),
Padding(
padding: EdgeInsets.symmetric(
horizontal: widget.innerHorizontalSymmetricPadding,
vertical: widget.innerVerticalSymmetricPadding,
),
child: Text(
widget.instrumentName,
style: globalTextStyle.copyWith(
color: Colors.black87,
fontSize: 14,
fontWeight: FontWeight.bold),
),
),
Row(
children: [
Padding(
padding: EdgeInsets.only(left: widget.width * 0.07)),
Text(
widget.instrumentPrice,
style: globalTextStyle.copyWith(
color: Colors.green.shade900,
fontWeight: FontWeight.bold,
fontSize: 14,
),
),
Padding(
padding: EdgeInsets.only(left: widget.width * 0.07)),
Text(
widget.instrumentMrp,
style: globalTextStyle.copyWith(
color: Colors.grey,
fontSize: 12,
decoration: TextDecoration.lineThrough,
),
),
],
),
Padding(padding: EdgeInsets.only(top: widget.height * 0.025)),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
width: widget.width / 2,
decoration: const BoxDecoration(
border: Border(
top: BorderSide(color: Colors.grey, width: 0.2),
right: BorderSide(color: Colors.grey, width: 0.2),
),
),
child: InkWell(
onTap: () {
// setState(() {
// isWishlisted = !isWishlisted;
// });
widget.onWishTap;
},
child: Padding(
padding: EdgeInsets.symmetric(
vertical: widget.height * 0.0125),
child: (isWishlisted)
? Icon(
Icons.favorite_rounded,
color: Colors.red.shade900,
)
: const Icon(
Icons.favorite_border_rounded,
color: Colors.black87,
),
),
),
),
Container(
width: widget.width / 2,
decoration: const BoxDecoration(
border: Border(
top: BorderSide(color: Colors.grey, width: 0.2),
right: BorderSide(color: Colors.grey, width: 0.2),
),
),
child: InkWell(
onTap: () {
// setState(() {
// isCarted = !isCarted;
// });
widget.onCartTap;
},
child: Padding(
padding: EdgeInsets.symmetric(
vertical: widget.height * 0.0125),
child: (isCarted)
? Icon(Icons.shopping_cart_rounded,
color: Colors.blue.shade900)
: const Icon(
Icons.shopping_cart_outlined,
color: Colors.black87,
),
),
),
),
],
),
],
),
),
Positioned(
right: 0,
top: widget.height * 0.075,
child: Container(
width: widget.width * 0.25,
height: widget.height * 0.07,
decoration: BoxDecoration(
color: Colors.green.shade900,
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(5),
bottomLeft: Radius.circular(5),
),
),
child: Padding(
padding: EdgeInsets.only(
left: widget.width * 0.04,
top: widget.height * 0.016,
),
child: Text(
widget.instrumentDiscount,
style: globalTextStyle.copyWith(
color: Colors.white70,
fontSize: 10,
fontWeight: FontWeight.bold,
),
),
),
),
),
],
),
),
);
}
}
global_variables.dart - a Dart file that contains the list of map elements of instrument items and also has empty lists declared for wishList and cartList where I intend to add/remove instrument items based on tapping the instrument item cards on the HomeWelcomeScreen
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import '../widgets/animated_bottom_bar.dart';
TextStyle globalTextStyle = GoogleFonts.lato();
const _inactiveColor = Colors.grey;
const _activeColor = Colors.white70;
List<Map<String, dynamic>> brandLogos = [
{
"brand": "fender",
"img-url":
"https://png.pngitem.com/pimgs/s/159-1597814_fender-guitar-hd-png-download.png",
},
{
"brand": "yamaha",
"img-url":
"https://www.motoroids.com/wp-content/uploads/2011/03/Yamaha-logo.jpg",
},
{
"brand": "ibanez",
"img-url":
"https://s0.bukalapak.com/img/57118379431/large/IBANEZ_GUITAR_sticker_logo_ibanez_gitar_stiker_murah_8cm.jpg",
},
{
"brand": "gibson",
"img-url":
"https://i.etsystatic.com/34531699/r/il/cd1ba7/3800299077/il_340x270.3800299077_1e91.jpg",
},
{
"brand": "tama",
"img-url": "https://www.vector-logo.net/logo_preview/eps/t/Tama.png",
},
];
List<Map<String, dynamic>> instruments = [
{
"instrument": "Guitar",
"name": "Fender Stratocaster",
"brand": "Fender",
"mrp": 62000,
"price": 58900,
"rating": 4.7,
"reviews": 11,
"img-url":
"https://cdn.shopify.com/s/files/1/0657/6821/products/FEN-0144522500_grande.jpg?v=1639964521",
},
{
"instrument": "Guitar",
"name": "Squier Bullet Strat",
"brand": "Fender",
"mrp": 17280,
"price": 11900,
"rating": 4.5,
"reviews": 188,
"img-url":
"https://cdn.shopify.com/s/files/1/0657/6821/products/SQUIERBULLETSTRAT_0934fec6-212d-4e8e-84d2-27c52f31c427_large.jpg?v=1653118647",
},
{
"instrument": "Guitar",
"name": "Les Paul Studio LT",
"brand": "Epiphone",
"mrp": 29999,
"price": 24604,
"rating": 4.4,
"reviews": 11,
"img-url":
"https://cdn.shopify.com/s/files/1/0657/6821/products/SQUIERBULLETSTRAT_0934fec6-212d-4e8e-84d2-27c52f31c427_large.jpg?v=1653118647",
},
{
"instrument": "Guitar",
"name": "KX 100 HT",
"brand": "Cort",
"mrp": 21542,
"price": 17176,
"rating": 5.0,
"reviews": 2,
"img-url":
"https://cdn.shopify.com/s/files/1/0657/6821/products/io_large.jpg?v=1640775516",
},
{
"instrument": "Guitar",
"name": "Jet-1",
"brand": "Aria",
"mrp": 15174,
"price": 14416,
"rating": 4.0,
"reviews": 1,
"img-url":
"https://cdn.shopify.com/s/files/1/0657/6821/products/ARI-JET1BK_large.jpg?v=1639700162",
},
];
List<Map<String, dynamic>> wishList = [];
List<Map<String, dynamic>> cartList = [];
My logic so far: I have tried calling VoidCallBack functions which when the relevant UI is tapped on will set the state in which the specific instrument card item will be added/removed from the wishlist or cart lists. Also, I have got two boolean propetries of the InstrumentCard, one each for isWishlisted and isCarted whose values will be toggled betwen true and false based on whether the specific instrument item is present or absent in the wishlist or cart. Their boolean values will be used for rendering the relvant icons (added - red/blue or empty - outlined) for the wishlist and cart.
Request: What is wrong with my logic and how will I add/remove items to the wishlist and cart?
Screenshot for reference:
To call a method inside tap you need to use (). Do it like
onTap: () {
setState(() {
isCarted = !isCarted;
});
widget.onCartTap(); //this
Related
I wants to show images from server to the flutter app.I have implemented below code please guide me why its not working
In below code at the end of the code I have created one widget but when I am passing doc to the widget its breaking the code by opening box.dart and errors_patch.dart files I couldn't get where I am making mistake.In list view builder i have checked for length of file. First I have to show icon and when tapped on Icon it should open the dialogue box with image inside it class PanDetails extends StatefulWidget { const PanDetails({Key? key}) : super(key: key); #override State<PanDetails> createState() => _PanDetailsState(); } class _PanDetailsState extends State<PanDetails> { TextEditingController panController = TextEditingController(); List<File?>? panDetailsImages; List panfiles = \[\]; #override void initState() { init(); super.initState(); } Future init() async { dynamic companyId = getIt<SharedPreferences>().getString('companyId'); //final docs = DioClient().KycDetails(companyId); dynamic responseData = await getIt<DioClient>().KycDetails(companyId); final details = responseData\['data'\]; Pan pandetails = Pan.fromJson(details\['pan'\]); setState(() { List<String> panfiles = pandetails.files; this.panfiles = panfiles; }); print('panfiles...))))))))))))${panfiles\[0\].toString()}'); } #override Widget build(BuildContext context) { return LayoutBuilder(builder: (context, constraints) { double maxHeight = constraints.maxHeight; double maxWidth = constraints.maxWidth; double h1p = maxHeight * 0.01; double h10p = maxHeight * 0.1; double w10p = maxWidth * 0.1; double w1p = maxWidth * 0.01; return SafeArea( child: Scaffold( backgroundColor: Colours.black, appBar: AppBar( elevation: 0, automaticallyImplyLeading: false, toolbarHeight: h10p * .9, flexibleSpace: AppbarWidget()), body: Container( width: maxWidth, decoration: const BoxDecoration( color: Colours.white, borderRadius: BorderRadius.only( topLeft: Radius.circular(10), topRight: Radius.circular(10), )), child: ListView(children: \[ InkWell( onTap: () { Navigator.pop(context); }, child: Padding( padding: EdgeInsets.symmetric( horizontal: w1p * 3, vertical: h1p * 3), child: Row( children: \[ SvgPicture.asset("assets/images/arrowLeft.svg"), SizedBox( width: w10p * .3, ), const Text( "PAN Details", style: TextStyles.leadingText, ), \], ), ), ), Padding( padding: EdgeInsets.only( left: w1p * 6, right: w1p * 6, top: h1p * 3), child: Container( decoration: BoxDecoration( boxShadow: \[ BoxShadow( color: Color(0x26000000), offset: Offset(0, 1), blurRadius: 1, spreadRadius: 0) \], color: Colours.paleGrey, ), child: TextFormField( controller: panController, decoration: InputDecoration( contentPadding: EdgeInsets.symmetric( horizontal: w1p * 6, vertical: h1p * .5), border: OutlineInputBorder( borderRadius: BorderRadius.circular(10), ), fillColor: Colours.paleGrey, hintText: "PAN Number", hintStyle: TextStyles.textStyle120, )), ), ), SizedBox( height: h1p * 3, ), Row( mainAxisAlignment: MainAxisAlignment.start, children: \[ DocumentUploading( maxWidth: maxWidth, maxHeight: maxHeight, onFileSelection: (files) { panDetailsImages = files; setState(() {}); }, ), SizedBox( width: 40, height: 50, child: ListView.builder( scrollDirection: Axis.horizontal, itemCount: panfiles.length, itemBuilder: (context, index) { final doc = panfiles\[index\]; // print(doc); return GestureDetector( child: imageDialog(doc.toString())); }, ), //_checkController(); ) \], ), InkWell( onTap: () async { Map<String, dynamic> panDetails = await getIt<KycManager>().storePanCardDetails( panController.text, filePath: panDetailsImages?.first?.path ?? ""); Fluttertoast.showToast(msg: panDetails\['msg'\]); // ScaffoldMessenger.of(context).showSnackBar(SnackBar( // behavior: SnackBarBehavior.floating, // content: Text( // panDetails\['msg'\], // style: const TextStyle(color: Colors.green), // ))); if (panDetails\['error'\] == false) { Navigator.pop(context); } }, child: Submitbutton( maxWidth: maxWidth, maxHeight: maxHeight, isKyc: true, content: "Save & Continue", )) \])))); }); } } Widget imageDialog(path) { return Dialog( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: \[ Container( width: 220, height: 200, child: Image.network( '$path', fit: BoxFit.cover, ), ), \], ),[![enter image description here][1]][1] ); }
How to access particular variable in another function call in flutter?
In the below code I want to access 'selectFront' and 'selectBack' variables from onTap() method of InkWell(). If I globally declare variable with late initialization it throws an error. What is the another good way to access those variables in another OnPressed() method of TextButton? import 'dart:convert'; import 'dart:io'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_svg/svg.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:image_picker/image_picker.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../../../Controller/adhaarController.dart'; import '../../../Model/AdhaarCapture.dart'; import '../../../logic/view_models/kyc_manager.dart'; import '../../../models/helper/service_locator.dart'; import '../../theme/constants.dart'; import '../../widgets/appbar/app_bar_widget.dart'; import '../../widgets/kyc_widgets/document_uploading.dart'; import '../../widgets/kyc_widgets/submitt_button.dart'; import 'getAdhaarDetails.dart'; import 'package:http/http.dart' as http; class AadhaarCard extends StatefulWidget { const AadhaarCard({Key? key}) : super(key: key); #override State<AadhaarCard> createState() => _AadhaarCardState(); } class _AadhaarCardState extends State<AadhaarCard> { TextEditingController aadhaarController = TextEditingController(); late File frontImage; late File backImage; late final Future<List<Data>> adhaarData; String? companyId = getIt<SharedPreferences>().getString('companyId'); #override Widget build(BuildContext context) { return LayoutBuilder(builder: (context, constraints) { double maxHeight = constraints.maxHeight; double maxWidth = constraints.maxWidth; double h1p = maxHeight * 0.01; double h10p = maxHeight * 0.1; double w10p = maxWidth * 0.1; double w1p = maxWidth * 0.01; return SafeArea( child: Scaffold( backgroundColor: Colours.black, appBar: AppBar( elevation: 0, automaticallyImplyLeading: false, toolbarHeight: h10p * .9, flexibleSpace: AppbarWidget()), body: Container( width: maxWidth, decoration: const BoxDecoration( color: Colours.white, borderRadius: BorderRadius.only( topLeft: Radius.circular(10), topRight: Radius.circular(10), )), child: ListView(children: [ InkWell( onTap: () { Navigator.pop(context); }, child: Padding( padding: EdgeInsets.symmetric( horizontal: w1p * 3, vertical: h1p * 3), child: Row( children: [ SvgPicture.asset("assets/images/arrowLeft.svg"), SizedBox( width: w10p * .3, ), const Text( "Aadhaar Details", style: TextStyles.leadingText, ), ], ), ), ), Padding( padding: EdgeInsets.only(left: w1p * 6, right: w1p * 6, top: h1p * 3), child: Container( decoration: BoxDecoration( boxShadow: [ BoxShadow( color: Color(0x26000000), offset: Offset(0, 1), blurRadius: 1, spreadRadius: 0) ], color: Colours.paleGrey, ), child: TextFormField( controller: aadhaarController, decoration: InputDecoration( contentPadding: EdgeInsets.symmetric( horizontal: w1p * 6, vertical: h1p * .5), border: OutlineInputBorder( borderRadius: BorderRadius.circular(10), ), fillColor: Colours.paleGrey, hintText: "Aadhaar Number", hintStyle: TextStyles.textStyle120, )), ), ), SizedBox( height: h1p * 3, ), Row( children: [ InkWell( onTap: () async { FilePickerResult? fileResult = (await FilePicker.platform .pickFiles(allowMultiple: false)); String? path = fileResult != null ? fileResult.files.isNotEmpty ? fileResult.files[0].path : "" : ""; final File selectFront = File(path as String); print(selectFront.readAsBytesSync()); }, child: Padding( padding: EdgeInsets.only( left: w1p * 6, right: w1p * 6, top: h1p * 1), child: Container( height: h1p * 6, width: w10p * 4, decoration: BoxDecoration( borderRadius: BorderRadius.circular(6), color: Colours.disabledText, ), child: Padding( padding: EdgeInsets.symmetric( horizontal: w1p * 2, vertical: h1p * 2), child: Row(children: [ InkWell( onTap: () async { XFile? fileResult = await ImagePicker() .pickImage(source: ImageSource.camera); String? path = fileResult != null ? fileResult.path.isNotEmpty ? fileResult.path : "" : ""; ImageSource.camera); final File selectFront = File(path as String); this.frontImage = selectFront; }, child: Container( child: Center( child: SvgPicture.asset( "assets/images/kycImages/camera.svg", height: h1p * 4), ), ), ), Text( 'Upload Front Image', style: TextStyles.textStyle121, ), ])) ), )), InkWell( onTap: () async { FilePickerResult? fileResult = (await FilePicker.platform .pickFiles(allowMultiple: false)); String? path = fileResult != null ? fileResult.files.isNotEmpty ? fileResult.files[0].path : "" : ""; final File selectBack = File(path as String); print(selectBack.readAsBytesSync()); this.backImage = selectBack; }, child: Padding( padding: EdgeInsets.only( left: w1p * 2, right: w1p * 5, top: h1p * 1), child: Container( height: h1p * 6, width: w10p * 4, decoration: BoxDecoration( borderRadius: BorderRadius.circular(6), color: Colours.disabledText, ), child: Padding( padding: EdgeInsets.symmetric( horizontal: w1p * 2, vertical: h1p * 2), child: Row(children: [ InkWell( onTap: () async { XFile? fileResult = await ImagePicker() .pickImage(source: ImageSource.camera); String? path = fileResult != null ? fileResult.path.isNotEmpty ? fileResult.path : "" : ""; // final selectFront = await ImagePicker() // .pickImage(source: ImageSource.camera); final File selectBack = File(path as String); this.backImage = selectBack; }, child: Container( child: SvgPicture.asset( "assets/images/kycImages/camera.svg", height: h1p * 4, ), ), ), // ), Text( 'Upload Back Image', style: TextStyles.textStyle121, ), ])), ), )), ], ), TextButton( onPressed: () async { final Future<List<Data>> adhaarData = AdhaarController.adhaarDetails( companyId, this.frontImage, this.backImage); print('this.img......${this.frontImage}'); print('this.img .....${this.backImage}'); print('adhaaar data........${adhaarData}'); setState(() { this.adhaarData = adhaarData; }); }, child: Text( 'CAPTURED', style: TextStyle(color: Colors.black), ), style: TextButton.styleFrom(side: BorderSide(color: Colors.grey)), ), InkWell( onTap: () async { await getIt<KycManager>().storeAadhaarProof( aadhaarController.text, ); // AdhaarController.adhaarDetails(companyId, , back) Fluttertoast.showToast(msg: "successfully uploaded"); Navigator.pop(context); }, child: Submitbutton( maxWidth: maxWidth, maxHeight: maxHeight, isKyc: true, content: "Save & Continue", )) ]), ), )); }); } }
i cant update itemcount
hey why is my itemcount not working i have 6 rows in my database but when i run the code it show me only one row and the other rows not showing it this is my code: import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; class my_ads extends StatefulWidget { const my_ads({Key? key}) : super(key: key); #override State<my_ads> createState() => _my_adsState(); } List list = []; int select_item = 0; class _my_adsState extends State<my_ads> { #override Future ReadData() async { var url = "https://***.***.***.**/getData.php"; var res = await http.get(Uri.parse(url)); if (res.statusCode == 200) { var red = jsonDecode(res.body); setState(() { list.addAll(red); }); print(list); } } #override void initState() { super.initState(); GetData(); } GetData() async { await ReadData(); } #override Widget build(BuildContext context) { return Scaffold( body: ListView.builder( itemCount: list.length, itemBuilder: ((cts, i) { return Container( height: 800, child: ListView( children: [ Container( margin: EdgeInsets.only(left: 70, right: 60), height: 54.0, width: 224.0, child: Container( decoration: BoxDecoration( border: Border.all( color: Color(0xffF4AC47), width: 5), color: Color(0xff42A9D2), borderRadius: BorderRadius.only( bottomLeft: Radius.circular(40), bottomRight: Radius.circular(40))), child: new Center( child: new Text( "MyAds", style: TextStyle( fontSize: 25, color: Color(0xff072A52), fontFamily: 'Cairo'), textAlign: TextAlign.center, ), //end logo )), ), ///start Section Container( margin: EdgeInsets.only(left: 10, right: 10, top: 10), height: 180.0, width: 430.0, child: Container( decoration: BoxDecoration( border: Border.all( color: Color(0xff42A9D2), width: 5), borderRadius: BorderRadius.circular(8)), child: new Container( child: Row( children: [ Expanded( child: Image( image: AssetImage("assets/book.jpg"), )), Container( margin: EdgeInsets.only( left: 110, top: 30, right: 13), child: Column( children: [ Text( "test", style: TextStyle( fontSize: 20, color: Colors.black87), ), SizedBox( height: 20, ), Row( children: [ Text("test2"), Icon(Icons.perm_identity_rounded) ], ), SizedBox( height: 5, ), Row( children: [ Text("}"), Column( children: [Icon(Icons.store)], ) ], ), ], ), ) ], ) //end logo )), ), ], ), ); }))); } } i tried to change ListView to ListTile but the design will be detroyed becuse i need to make the same design to other pages but my problem is with itemcount its not making any changes ! please if you have any ideas with my problem give me ansewrs
How to prevent repeated API Calls upon Navigating back and forth between screens in Flutter
The issue I'm having right now is that a particular API is getting called repeatedly no matter what I do. I have thought of several ways to avert this but this keeps happening time and again every time I move back and forth between pages. The data that I'm having to deal with is of type Map<String, dynamic> and I've tried placing a check which you will find below in my code. This check was inspired by an earlier code where I had managed to prevent repeated API calls by checking if the data received from API exists or not. The only difference then was that the date set I had to place the check against was of type List<dynamic> the code for which is also below. I would like to know what I can do to prevent repeated API calls on a page when I navigate to and fro. The code extract that worked(List<dynamic>) class CategoryProvider with ChangeNotifier { String baseUrl = 'http://*********'; List<dynamic> _category = []; List<dynamic> get category { return [..._category]; } List<dynamic> get categoriesList { return [..._categoriesList]; } Future<void> getCategory() async { final url = Uri.parse(baseUrl + 'api/category-list/'); print('Before Category API Call: $_category'); if (_category.length < 1) { //This here is a simple check which will basically detemine wether or not the API call needs to happen final response = await http.get(url); _category = json.decode(response.body); print('CATEGORY API CALLLLLLLLL'); } print('Categoryssssssssssssss $_category'); } } The widget where this has been implemented: class Categories extends StatefulWidget { CategoriesState createState() => CategoriesState(); } class CategoriesState extends State<Categories> { bool isLoading = true; #override void initState() { // TODO: implement initState Provider.of<CategoryProvider>(context, listen: false) .getCategory() .then((_) { setState(() { isLoading = false; }); }); super.initState(); } #override Widget build(BuildContext context) { final height = MediaQuery.of(context).size.height; final width = MediaQuery.of(context).size.width; final tabLayout = width > 600; final largeLayout = width > 350 && width < 600; final provider = Provider.of<CategoryProvider>(context, listen: false).category; return Padding( padding: EdgeInsets.only(left: width * 0.04, right: width * 0.04), child: Container( width: width * 0.9, height: !tabLayout && !largeLayout ? height * 0.28 : height * 0.25, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(20), boxShadow: const [ BoxShadow(color: Colors.grey, blurRadius: 5, offset: Offset(0, 2)) ]), child: Column( children: [ Padding( padding: EdgeInsets.only( left: width * 0.04, top: height * 0.01, right: width * 0.04), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Categories', // textScaleFactor: textScaleFactor, style: TextStyle( color: Colors.black, fontWeight: FontWeight.bold, fontSize: tabLayout ? 25 : largeLayout ? 17 : 12), ), InkWell( onTap: () => Navigator.of(context).pushNamed('/category-screen'), child: Text( 'View All', // textScaleFactor: textScaleFactor, style: TextStyle( color: Colors.greenAccent, fontSize: tabLayout ? 18 : largeLayout ? 14 : 10), ), ) ], ), ), Expanded( child: isLoading ? const Center( child: CircularProgressIndicator( color: Colors.green, ), ) : Container( width: double.infinity, height: height * 0.1, margin: EdgeInsets.only(top: height * 0.01), padding: EdgeInsets.only( left: width * 0.02, top: height * 0.005, right: width * 0.02, bottom: height * 0.008), decoration: BoxDecoration( // color: Colors.red, borderRadius: BorderRadius.circular(20), ), child: ListView.builder( scrollDirection: Axis.horizontal, itemBuilder: (context, index) => Container( width: width * 0.3, height: height * 0.06, // padding: EdgeInsets.fromLTRB(width * 0.02, height * 0.01, // width * 0.02, height * 0.01), margin: EdgeInsets.only(right: width * 0.02), padding: EdgeInsets.only( left: width * 0.02, right: width * 0.02), // color: Colors.green, child: Column( mainAxisAlignment: MainAxisAlignment.start, children: [ Padding( padding: EdgeInsets.only(top: height * 0.004), child: InkWell( onTap: () => Navigator.of(context) .push(MaterialPageRoute( builder: (context) => CategoryList( provider[index]['id'], provider[index]['name']), )), child: Container( width: double.infinity, height: tabLayout ? height * 0.14 : largeLayout ? height * 0.12 : height * 0.15, decoration: BoxDecoration( color: Colors.green[100], borderRadius: BorderRadius.circular(20), ), child: Image.network( provider[index]['categoryImage']), ), ), ), SizedBox(height: height * 0.01), Text( provider[index]['name'], textAlign: TextAlign.center, // textScaleFactor: textScaleFactor, style: TextStyle( color: Colors.black, fontWeight: FontWeight.bold, fontSize: tabLayout ? width * 0.02 : largeLayout ? 14 : 12), ) ], ), ), itemCount: provider.length, ), ), ) ], ), ), ); } } The code for the check against type Map<String, dynamic> which doesn't work: import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; class PopularDealsProvider with ChangeNotifier { String baseUrl = 'http://**********'; Map<String, dynamic> _popularDeals = {}; Map<String, dynamic> get popularDeals { return {..._popularDeals}; } Future<void> getPopularDeals() async { print('Before API Call: $_popularDeals'); if (_popularDeals == {}) { //This check was meant to make the call only if _popularDeals was a blank Map final url = Uri.parse(baseUrl + 'api/dashboard/popular/ordered-product/'); final response = await http.get(url); var res = json.decode(response.body); _popularDeals = res; print('API Called'); } print('PopularDeals $_popularDeals'); } } The widget where this has been implemented: class PopularDeals extends StatefulWidget { PopularDealsState createState() => PopularDealsState(); } class PopularDealsState extends State<PopularDeals> { bool isLoading = true; #override void initState() { // TODO: implement initState Provider.of<PopularDealsProvider>(context, listen: false) .getPopularDeals() .then((_) { setState(() { isLoading = false; }); }); itemDetail; super.initState(); } void itemDetail(int categoryId) async { Provider.of<CategoryProductsProvider>(context, listen: false) .getCategoryProducts(categoryId); } #override Widget build(BuildContext context) { final height = MediaQuery.of(context).size.height; final width = MediaQuery.of(context).size.width; // final textScaleFactor = MediaQuery.of(context).textScaleFactor * 1.2; final tabLayout = width > 600; final largeLayout = width > 350 && width < 600; final provider = Provider.of<PopularDealsProvider>(context).popularDeals; final productsProvider = Provider.of<CategoryProductsProvider>(context).categoryProducts; // TODO: implement build return isLoading ? const Center( child: CircularProgressIndicator( color: Colors.green, ), ) : Padding( padding: EdgeInsets.only(left: width * 0.04, right: width * 0.04), child: Container( width: width * 0.9, height: tabLayout ? height * 0.35 : largeLayout ? height * 0.34 : height * 0.35, margin: EdgeInsets.only(bottom: height * 0.04), decoration: BoxDecoration( color: Colors.green[50], borderRadius: BorderRadius.circular(20), boxShadow: const [ BoxShadow( color: Colors.grey, blurRadius: 5, offset: Offset(0, 2)) ]), child: Column( children: [ Padding( padding: EdgeInsets.only( left: width * 0.04, top: height * 0.01, right: width * 0.04), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Popular Deals', // // textScaleFactor: textScaleFactor, style: TextStyle( color: Colors.black, fontWeight: FontWeight.bold, fontSize: tabLayout ? 25 : largeLayout ? 17 : 12), ), Text( 'View All', // // textScaleFactor: textScaleFactor, style: TextStyle( color: Colors.green, fontWeight: FontWeight.bold, fontSize: tabLayout ? 18 : largeLayout ? 14 : 10), ) ], ), ), Expanded( child: Container( width: double.infinity, height: height * 0.1, padding: EdgeInsets.fromLTRB(width * 0.02, height * 0.005, width * 0.02, height * 0.008), margin: EdgeInsets.only(top: height * 0.01), decoration: const BoxDecoration( // color: Colors.red, borderRadius: BorderRadius.only( bottomLeft: Radius.circular(20), bottomRight: Radius.circular(20)), ), child: ListView.builder( scrollDirection: Axis.horizontal, itemBuilder: (context, index) => Container( width: tabLayout ? width * 0.35 : width * 0.45, height: double.infinity, margin: EdgeInsets.only(right: width * 0.02), padding: const EdgeInsets.all(5), // color: Colors.amber, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(30), boxShadow: const [ BoxShadow( color: Colors.grey, blurRadius: 5, offset: Offset(1, 2)) ]), child: InkWell( onTap: () => Navigator.of(context) .pushNamed('/item-details', arguments: { 'id': provider['data'][index][0]['id'], 'image': provider['data'][index][0] ['main_image'], 'name': provider['data'][index][0] ['name'], 'quantity': 0, 'description': provider['data'][index][0] ['description'], 'price': provider['data'][index][0] ['price'] }), child: Image.network( 'http://54.80.135.220${provider['data'][index][0]['main_image']}', fit: BoxFit.contain, width: tabLayout ? width * 0.35 : largeLayout ? width * 0.45 : width * 0.46, height: tabLayout ? height * 0.24 : largeLayout ? height * 0.2 : height * 0.22, ), ), ), SizedBox(height: height * 0.01), Padding( padding: EdgeInsets.only(left: width * 0.03), child: Text( provider['data'][index][0]['name'], // // textScaleFactor: textScaleFactor, style: TextStyle( color: Colors.black, fontWeight: FontWeight.bold, fontSize: tabLayout ? width * 0.02 : largeLayout ? 14 : 12), ), ), Padding( padding: EdgeInsets.only(left: width * 0.03), child: Text( '₹${provider['data'][index][0]['price']}/${provider['data'][index][0]['uom']['short_name']}', // // textScaleFactor: textScaleFactor, style: TextStyle( color: Colors.black, fontWeight: FontWeight.bold, fontSize: tabLayout ? width * 0.02 : largeLayout ? 14 : 1)), ), ]), ), itemCount: provider['data'].length, //The error gets thrown at this line ), ), ) ], ), ), ); } } This is what the error says: The getter 'length' was called on null. Receiver: null Tried calling: length Is there anyone who can help?? P.S I have already managed this with data that is of type of List<dynamic>. I just need a way to do the same with type Map<String, dynamic>
You can use any one of these to save the states and precvent repeated API calls: IndexedStack https://api.flutter.dev/flutter/widgets/IndexedStack-class.html PageStorageKey https://api.flutter.dev/flutter/widgets/PageStorageKey-class.html AutomaticKeepAliveClientMixin https://api.flutter.dev/flutter/widgets/AutomaticKeepAliveClientMixin-mixin.html
Buttons center their children when they are placed in a ListView.builder widget
Why do buttons in Flutter tend to align their children to the centre when they are placed in list views? For example: import 'package:flutter/material.dart'; class Test extends StatefulWidget { #override _TestState createState() => _TestState(); } class _TestState extends State<Test> { #override Widget build(BuildContext context) { return Scaffold( body: ListView.builder( itemCount: 10, itemBuilder: (context, index){ return MaterialButton( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text("Hello"), ], )); } ), ); } } This would result in ten hellos spaced evenly by the default height of the button, but they would be centered; even though I used the CrossAxisAlignment.start property in a column. Here is the image: But when I replace the MaterialButton with a Container they are aligned to the start to the column as wanted. When I just remove the ListView.Builder I get 'hello' aligned to the start. The same thing happens with the rest of the buttons. Is there a way to make buttons in list views not have centered children inside them? Edit: the example was fixed by #Harry but it didn't fix my exact code here is my code: I try to created a list of widgets outside and use a function to add my list items into that list and return a list view through the ActivitiesList widget import 'package:flutter/material.dart'; import 'package:list_them_out/models/activities.dart'; import 'package:provider/provider.dart'; class ActivitiesList extends StatefulWidget { #override _ActivitiesListState createState() => _ActivitiesListState(); } double conBorderRadius = 30; class _ActivitiesListState extends State<ActivitiesList> { List<Widget> itemData = []; void getData(context) { double cardHeight = MediaQuery.of(context).size.height * 0.3; double cardWidth = MediaQuery.of(context).size.width * 0.97; final activities = Provider.of<List<Activity>>(context); activities == null // ignore: unnecessary_statements ? null : setState(() { itemData = []; }); activities == null // ignore: unnecessary_statements ? null : setState(() { activities.forEach((element) { itemData.add(Padding( padding: EdgeInsets.symmetric(horizontal: 10), child: Container( width: cardWidth, decoration: BoxDecoration( borderRadius: BorderRadius.circular(conBorderRadius), gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: <Color>[ Colors.lightGreen[300], Colors.lightBlue[300], ] ), boxShadow: [ BoxShadow( color: Colors.grey[600], offset: Offset(4.0, 4.0), blurRadius: 15, spreadRadius: 1), BoxShadow( color: Colors.white, offset: Offset(-4.0, -4.0), blurRadius: 15, spreadRadius: 1), ]), child: Stack( children: [ ClipRRect( borderRadius: BorderRadius.circular(conBorderRadius), child: MaterialButton( splashColor: HSLColor.fromColor(Colors.green).toColor(), onPressed: () {}, child: Align( alignment: Alignment.centerLeft, child: Container( child: Padding( padding: EdgeInsets.only(top: 20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( width: cardWidth * 0.61, child: Text( element.name, maxLines: 2, overflow: TextOverflow.ellipsis, style: TextStyle( color: Colors.grey[600], fontSize: 25, fontWeight: FontWeight.w500, letterSpacing: 1, ), ), ), Padding( padding: EdgeInsets.only(top: cardHeight * 0.09, left: cardWidth * 0.03), child: Container( width: cardWidth * 0.48, child: RichText( maxLines: 2, overflow: TextOverflow.ellipsis, text: TextSpan(children: [ TextSpan( text: "Start: ", style: TextStyle( color: Colors.grey[800], fontSize: 20, fontWeight: FontWeight.w400, letterSpacing: 1), ), TextSpan( text: element.time, style: TextStyle( color: Colors.black87, fontWeight: FontWeight.w300, fontSize: 20, )) ]), ), ), ), SizedBox(height: cardHeight * 0.06,), Row( children: [ IconButton(icon: Icon(Icons.comment), onPressed: () => null, color: Colors.grey[600], ), Padding( padding: EdgeInsets.only(bottom: 5), child: Text("Comments", style: TextStyle(color: Colors.grey[600], fontSize: 20, fontWeight: FontWeight.w300, letterSpacing: 1),), ) ], ) ], ), ),), ), ), ), Positioned( right: 0, bottom: 0, top: 0, child: ClipPath( clipper: MyClip(radius: conBorderRadius), child: Container( height: cardHeight, width: cardWidth * 0.45, decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: <Color>[ Colors.grey[300], Colors.lightBlue[100].withOpacity(0.5) ])), ), ), ), Positioned( right: cardWidth * 0.05, bottom: 20, child: Container( child: Text("Hello"), ), ) ], )), )); }); }); } #override Widget build(BuildContext context) { double listHeight = MediaQuery.of(context).size.height * 0.86; double listWidth = MediaQuery.of(context).size.width * 0.97; getData(context); return ClipRRect( borderRadius: BorderRadius.only( topRight: Radius.circular(50), topLeft: Radius.circular(50)), child: Container( height: listHeight, width: listWidth, child: ListView.builder( itemCount: itemData.length, itemBuilder: (context, index) { return Padding( padding: EdgeInsets.only(bottom: 30), child: itemData[index], ); }), )); } } ``
Try using the Align widget. Just wrap the column with an align widget and have the alignment parameter be alignment.centerLeft. import 'package:flutter/material.dart'; class Test extends StatefulWidget { #override _TestState createState() => _TestState(); } class _TestState extends State<Test> { #override Widget build(BuildContext context) { return Scaffold( body: ListView.builder( itemCount: 10, itemBuilder: (context, index){ return MaterialButton( child: Align( child:Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text("Hello"), ], ), alignment: Alignment.centerLeft, ) ); } ), ); } }