Flutter添加到收藏夹按钮选择所有项目和

5jvtdoz2  于 2023-03-19  发布在  Flutter
关注(0)|答案(2)|浏览(126)

我正在建立一个flutter电子商务应用程序,我有一个问题,如果我点击添加到收藏夹按钮,它选择所有项目,而不是选定的特定项目。我的项目是在一个网格视图使用标签栏。请任何人可以帮助。
以下是选择

之前的项目
然后在选择之后(如您所见,所有项目均已选中)

下面是我的代码模型:

//Bottle and Bottle Category Model classes
class Bottle with ChangeNotifier {
  String id;
  String bottleName;
  String image;
  String bottletype;
  int time;
  double price;
  bool isFavourite;
  Bottle(
      {required this.id,
      required this.bottleName,
      required this.image,
      required this.bottletype,
      required this.time,
      required this.price,
      this.isFavourite = false});

  void isFavoritePressed() {
    isFavourite = !isFavourite;
    notifyListeners();
  }
}

class BottleCategory {
  int categoryNo;
  String bottleType;
  List<Bottle> bottleList;
  BottleCategory(
      {required this.categoryNo,
      required this.bottleType,
      required this.bottleList});
}
//Cart Model Class
class Cart with ChangeNotifier {
  String id;
  String bottleName;
  String image;
  double price;
  int quantity;
  Cart({
    required this.id,
    required this.bottleName,
    required this.image,
    required this.price,
    required this.quantity,
  });
}

class ProductItem extends StatelessWidget {
  HomePage homeInstance = const HomePage();
  String id;
  String bottleName;
  String imgUrl;
  double price;
  bool isFavourite;
  ProductItem(
      {Key? key,
      required this.id,
      required this.bottleName,
      required this.imgUrl,
      required this.price,
      this.isFavourite = false})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    var cart = Provider.of<ShoppingCartProvider>(context);
    var product = Provider.of<Bottle>(context);
    return Card(
      shadowColor: Colors.grey,
      surfaceTintColor: Colors.amber,
      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
      child: Stack(
        children: [
          Positioned(
            right: 0,
            child: InkWell(
              onTap: () {
                product.isFavoritePressed();
                if (product.isFavourite) {
                  ScaffoldMessenger.of(context).hideCurrentSnackBar();
                  ScaffoldMessenger.of(context).showSnackBar(
                    const SnackBar(
                      content: Text(
                        "Product Added to Favorite!",
                        style: TextStyle(fontSize: 16),
                      ),
                      backgroundColor: Colors.green,
                      duration: Duration(seconds: 1),
                    ),
                  );
                } else {
                  ScaffoldMessenger.of(context).hideCurrentSnackBar();
                  ScaffoldMessenger.of(context).showSnackBar(
                    const SnackBar(
                      content: Text(
                        "Product Removed from Favorite!",
                        style: TextStyle(fontSize: 16),
                      ),
                      backgroundColor: Colors.red,
                      duration: Duration(seconds: 1),
                    ),
                  );
                }
              },
              child: Icon(
                product.isFavourite ? Icons.favorite : Icons.favorite_border,
                size: 25,
                color: Colors.redAccent,
              ),
            ),
          ),
          Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Center(
                child: Image.asset(
                  imgUrl,
                  height: 200.0,
                ),
              ),
              Center(
                  child: Text(bottleName,
                      style: const TextStyle(
                          fontSize: 20.0, fontWeight: FontWeight.bold))),
              Center(
                child: Text('R$price'),
              )
            ],
          ),
          Positioned(
              bottom: 0,
              right: 10,
              child: IconButton(
                icon: const Icon(Icons.add_circle),
                iconSize: 40.0,
                onPressed: () {
                  cart.addToCart(id, bottleName, price, imgUrl);
                },
              ))
        ],
      ),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
  ProductProvider productProvider = ProductProvider();
  late TabController tabController;
  late Bottle bottleProvider;

  String query = " ";

  Widget buildSearch() {
    return SearchWidget(
      text: query,
      hintText: 'Search for beverages',
      onChanged: (value) {
        setState(() {
          this.query = value;
        });
      },
    );
  }

  @override
  void initState() {
    super.initState();
    tabController = TabController(length: 4, vsync: this);
  }

  @override
  void dispose() {
    tabController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    var cart = Provider.of<ShoppingCartProvider>(context);
    Size _screenSize = MediaQuery.of(context).size;
    final double itemHeight = (_screenSize.height - kToolbarHeight - 24) / 2;
    final double itemWidth = _screenSize.width / 2;
    return Scaffold(
      body: SingleChildScrollView(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            buildSearch(),
            const Padding(
              padding: EdgeInsets.all(8.0),
              child: Text(
                'Categories',
                style: TextStyle(
                    fontSize: 20.0,
                    fontFamily: 'Montserrat-ExtraBold',
                    fontWeight: FontWeight.bold),
              ),
            ),
            Container(
              child: Align(
                alignment: Alignment.centerLeft,
                child: TabBar(
                  controller: tabController,
                  indicator:
                      CircleTabIndicator(color: Colors.redAccent, radius: 4.0),
                  isScrollable: true,
                  labelColor: Colors.redAccent,
                  labelStyle: const TextStyle(
                      fontWeight: FontWeight.bold, fontSize: 20.0),
                  unselectedLabelColor: Colors.black,
                  unselectedLabelStyle: const TextStyle(
                      fontWeight: FontWeight.bold, fontSize: 20.0),
                  tabs: const [
                    Tab(text: 'Brandy'),
                    Tab(text: 'Gin'),
                    Tab(text: 'Soft drinks'),
                    Tab(text: 'Whiskey')
                  ],
                ),
              ),
            ),
            Container(
              height: 400,
              width: double.maxFinite,
              child: TabBarView(
                  controller: tabController,
                  children: productProvider.categories.map((bottleCategory) {
                    return GridView.count(
                      crossAxisCount: 2,
                      childAspectRatio: itemWidth / itemHeight,
                      children: bottleCategory.bottleList.where((element) {
                        return element.bottleName.toLowerCase().contains(
                            query.toLowerCase()); // Apply the query string
                      }).map((bottle) {
                        return ProductItem(
                          id: bottle.id,
                          bottleName: bottle.bottleName,
                          imgUrl: bottle.image,
                          price: bottle.price,
                        );
                      }).toList(),
                    );
                  }).toList()),
            ),
          ],
        ),
      ),
    );
  }
}
//ProductProvider
class ProductProvider with ChangeNotifier {
  final List<BottleCategory> categories = [
    BottleCategory(categoryNo: 1, bottleType: 'Brandy', bottleList: [
      Bottle(
          id: 'KLPB',
          bottleName: 'Klipdrift Brandy',
          image: 'lib/assets/images/KlipdriftBrandy.png',
          time: 20,
          price: 274.00,
          bottletype: 'Brandy'),
      Bottle(
          id: 'KWV3',
          bottleName: 'Kwv Brandy 3 years',
          image: 'lib/assets/images/KwvBrandy3years.jpg',
          time: 20,
          price: 274.00,
          bottletype: 'Brandy'),
    ]),
    BottleCategory(categoryNo: 2, bottleType: 'Gin', bottleList: [
      Bottle(
          id: 'BMBS',
          bottleName: 'Bombay Sapphire Gin',
          image: 'lib/assets/images/BombaySapphireGin.png',
          time: 20,
          price: 274.00,
          bottletype: 'Gin'),
      Bottle(
          id: 'TNGN',
          bottleName: 'Tanqueray Gin',
          image: 'lib/assets/images/TanquerayGin.png',
          time: 20,
          price: 274.00,
          bottletype: 'Gin'),
    ]),
    BottleCategory(categoryNo: 3, bottleType: 'Soft Drinks', bottleList: [
      Bottle(
          id: 'COCA',
          bottleName: 'Coca Cola',
          image: 'lib/assets/images/CocaCola.jpg',
          time: 20,
          price: 274.00,
          bottletype: 'Soft Drinks'),
      Bottle(
          id: 'SPRT',
          bottleName: 'Sprite',
          image: 'lib/assets/images/Sprite.jpg',
          time: 20,
          price: 274.00,
          bottletype: 'Soft Drinks'),
    ]),
    BottleCategory(categoryNo: 4, bottleType: 'Whiskey', bottleList: [
      Bottle(
          id: '',
          bottleName: 'Jameson',
          image: 'lib/assets/images/Jameson.jpg',
          time: 20,
          price: 274.00,
          bottletype: 'Whiskey'),
      Bottle(
          id: '',
          bottleName: 'Johnnie Walker Black Label',
          image: 'lib/assets/images/JohnnieWalkerBlackLabel.jpg',
          time: 20,
          price: 274.00,
          bottletype: 'Whiskey'),
    ]),
  ];
  List<Bottle> get bottleItems {
    return [...bottleItems];
  }

  List<Bottle> get bottleObjects {
    return [...bottleObjects];
  }

  get bottle => null;

  List<Bottle> get selectedFavorite {
    return categories
        .expand((bottleCategory) {
          return bottleCategory.bottleList;
        })
        .toList()
        .where((bottle) {
          return bottle.isFavourite;
        })
        .toList();
  }
}

//Cart Provider
import 'package:flutter/cupertino.dart';
import 'package:test_code/cart.dart';

class ShoppingCartProvider with ChangeNotifier {
  final Map<String, Cart> _cartItems = {};

  Map<String, Cart> get cartItem {
    return {..._cartItems};
  }

  void removeBottle(String id) {
    _cartItems.remove(id);
    notifyListeners();
  }

  void addToCart(
      String id, String bottleName, double bottlePrice, String image) {
    if (_cartItems.containsKey(id)) {
      _cartItems.update(id, (existingItem) {
        return Cart(
            id: existingItem.id,
            bottleName: existingItem.bottleName,
            image: existingItem.image,
            price: existingItem.price,
            quantity: existingItem.quantity + 1);
      });
    } else {
      _cartItems.putIfAbsent(id, () {
        return Cart(
            id: id,
            bottleName: bottleName,
            image: image,
            price: bottlePrice,
            quantity: 1);
      });
    }
    notifyListeners();
  }

  void addQuantity(String id) {
    _cartItems.update(id, (existingItem) {
      return Cart(
          id: existingItem.id,
          bottleName: existingItem.bottleName,
          image: existingItem.image,
          price: existingItem.price,
          quantity: existingItem.quantity + 1);
    });
    notifyListeners();
  }

  void reduceQuantity(String id) {
    _cartItems.update(id, (existingItem) {
      if (existingItem.quantity == 1) {
        return Cart(
            id: existingItem.id,
            bottleName: existingItem.bottleName,
            image: existingItem.image,
            price: existingItem.price,
            quantity: existingItem.quantity);
      } else {
        return Cart(
            id: existingItem.id,
            bottleName: existingItem.bottleName,
            image: existingItem.image,
            price: existingItem.price,
            quantity: existingItem.quantity - 1);
      }
    });
    notifyListeners();
  }

  void clearCart() {
    _cartItems.clear();
    notifyListeners();
  }

  double get totalAmount {
    double total = 0.0;
    _cartItems.forEach((key, eachItem) {
      total = total + eachItem.price * eachItem.quantity;
    });
    return total;
  }

  int get cartCount {
    return _cartItems.length;
  }
}
fae0ux8s

fae0ux8s1#

你可以玩小工具来了解项目选择模式。

class HomePageX extends StatefulWidget {
  const HomePageX({Key? key}) : super(key: key);

  @override
  State<HomePageX> createState() => _HomePageXState();
}

class _HomePageXState extends State<HomePageX> {
  List<int> selectedIndex = [];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: GridView.builder(
        gridDelegate:
            SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
        itemBuilder: (context, index) {
          return ProductItem(
            isFavorite: selectedIndex.contains(index),
            onTap: () {
              if (selectedIndex.contains(index)) {
                selectedIndex.remove(index);
              } else {
                selectedIndex.add(index);
              }

              setState(() {});
            },
          );
        },
      ),
    );
  }
}

class ProductItem extends StatelessWidget {
  final bool isFavorite;
  final VoidCallback onTap;
  const ProductItem({
    Key? key,
    required this.isFavorite,
    required this.onTap,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: onTap,
      child: Card(
        child: Container(
          color: isFavorite ? Colors.blue : Colors.grey,
        ),
      ),
    );
  }
}
bvjveswy

bvjveswy2#

我自己解决了这个问题。我只是把按钮移到一个单独的小部件上。我不知道它是怎么工作的,但它帮了我。

class FavoriteButtonWidget extends StatefulWidget {
  const FavoriteButtonWidget({Key? key}) : super(key: key);

  @override
  State<FavoriteButtonWidget> createState() => _FavoriteButtonWidgetState();
}

class _FavoriteButtonWidgetState extends State<FavoriteButtonWidget> {
  late Box box;
  late bool _isFavorite;

  @override

  void initState() {
    super.initState();
    box = Hive.box('favorites');
    final data = box.get("favorites");
    _isFavorite = data ?? false;
  }

  @override
  Widget build(BuildContext context) {
    return IconButton(
      onPressed: () {
        setState(() {
          _isFavorite = !_isFavorite;
        });
        box.put("favorites", _isFavorite);
      },
      icon: _isFavorite
          ? const Icon(
              Icons.favorite_border,
              color: UiKitColors.red,
            )
          : const Icon(
              Icons.favorite,
              color: UiKitColors.red,
            ),
    );
  }
}

相关问题