Home > Software design >  Unable to add elements to a List in Flutter
Unable to add elements to a List in Flutter

Time:08-06

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:

enter image description here

CodePudding user response:

To call a method inside tap you need to use (). Do it like

 onTap: () {
     setState(() {
       isCarted = !isCarted;
      });
   widget.onCartTap(); //this
  • Related