Menu
CoddyTech

Alışveriş Sepeti: Toplam Tutar

Coddy'nin Flutter Journey'sinin Durum Yönetimi bölümünün bir parçası. Ders 25 / 27.

Sepet ekranında bir toplam tutar gerekir. Toplam tutar yeni bir veri değildir: sepette bulunanlardan hesaplanır. Bu yüzden hiçbir yerde saklanmaz. Sepeti izleyen ve fiyatları fold ile toplayan bir provider'dır:

final totalProvider = Provider((ref) {
  final cart = ref.watch(cartProvider);
  return cart.fold(0.0, (sum, product) => sum + product.price);
});

Sepeti izlediği için sepet her değiştiğinde toplam tutar yeniden hesaplanır ve toplamı izleyen her widget yeni tutarı gösterir.

Toplam tutarı listenin altında göster. Scaffold'un bottomNavigationBar yuvası herhangi bir widget'ı alır ve liste kaydırılsa bile onu ekranın altında, listenin alt kısmında tutar.

challenge icon

Görev

Orta

Toplamı sepet ekranında göster:

  • cartProvider'ı izleyen ve fiyatları toplayan bir totalProvider ekle.
  • Sepet ekranında, biraz dolgu boşluğu bırakarak Scaffold'un bottomNavigationBar alanında Total: $2.75 (iki ondalık basamakla) göster.

Kendin dene

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: const Text('Shop'),
        actions: [
          IconButton(
            icon: Badge(
              label: Text('${cart.length}'),
              isLabelVisible: cart.isNotEmpty,
              child: const Icon(Icons.shopping_cart),
            ),
            onPressed: () {
              Navigator.push(
                context,
                MaterialPageRoute(builder: (context) => const CartScreen()),
              );
            },
          ),
        ],
      ),
      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);
                },
              ),
            ),
        ],
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final cart = ref.watch(cartProvider);
    return Scaffold(
      appBar: AppBar(title: const Text('Your cart')),
      body: cart.isEmpty
          ? const Center(child: Text('Your cart is empty'))
          : ListView(
              children: [
                for (final product in cart)
                  ListTile(
                    title: Text(product.name),
                    trailing: Text('\$${product.price.toStringAsFixed(2)}'),
                  ),
              ],
            ),
    );
  }
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Durum Yönetimi bölümündeki tüm dersler

Kendi başına pratik yap: Online Flutter derleyicisi