Menu
CoddyTech

Giỏ hàng: Huy hiệu

Thuộc phần Quản lý trạng thái trong hành trình Flutter của Coddy. Bài học 23 trên 27.

Các cửa hàng hiển thị giỏ hàng bằng một biểu tượng có gắn con số nhỏ, gọi là huy hiệu. Flutter có một widget để làm việc này: Badge hiển thị label trong bong bóng màu đỏ ở góc của child:

IconButton(
  icon: Badge(
    label: Text('${cart.length}'),
    isLabelVisible: cart.isNotEmpty,
    child: const Icon(Icons.shopping_cart),
  ),
  onPressed: () {},
)

isLabelVisible ẩn bong bóng khi giá trị là false. Giỏ hàng trống sẽ hiển thị biểu tượng đơn giản, trông dễ chịu hơn con số 0. cart.isNotEmpty có giá trị true khi danh sách có ít nhất một món hàng.

Huy hiệu theo dõi cùng cartProvider mà tiêu đề đã dùng. Widget nào cũng có thể theo dõi, dù nó nằm ở đâu.

challenge icon

Thử thách

Dễ

Chuyển số lượng từ tiêu đề sang huy hiệu:

  • Đưa tiêu đề về lại Shop.
  • Thêm một IconButton giỏ hàng vào actions trên thanh trên cùng, đặt Icons.shopping_cart bên trong Badge để hiển thị số lượng sản phẩm.
  • Ẩn số trên huy hiệu khi giỏ hàng trống.

Nút chưa làm gì cả; tiếp theo là màn hình giỏ hàng.

Tự làm thử

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

class Product {
  const Product(this.name, this.price);

  final String name;
  final double price;
}

const products = [
  Product('Apple', 0.5),
  Product('Bread', 2.25),
  Product('Cheese', 4),
  Product('Milk', 1.2),
];

class Cart extends Notifier<List<Product>> {
  @override
  List<Product> build() => [];

  void add(Product product) {
    state = [...state, product];
  }
}

final cartProvider = NotifierProvider<Cart, List<Product>>(Cart.new);

void main() {
  runApp(const ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: ShopPage(),
    );
  }
}

class ShopPage extends ConsumerWidget {
  const ShopPage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final cart = ref.watch(cartProvider);
    return Scaffold(
      appBar: AppBar(title: Text('Shop (${cart.length})')),
      body: ListView(
        children: [
          for (final product in products)
            ListTile(
              title: Text(product.name),
              subtitle: Text('\$${product.price.toStringAsFixed(2)}'),
              trailing: IconButton(
                icon: const Icon(Icons.add_shopping_cart),
                onPressed: () {
                  ref.read(cartProvider.notifier).add(product);
                },
              ),
            ),
        ],
      ),
    );
  }
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Quản lý trạng thái

Tự luyện tập: Trình biên dịch Flutter online