Negozio: Aggiungi al carrello
Fa parte della sezione Progetti del percorso Flutter di Coddy. Lezione 22 di 36.
Il carrello serve in due schermate: la pagina del prodotto vi aggiunge articoli e la griglia mostra quanti ce ne sono. I dati necessari a più di una schermata vanno inseriti in un modello, condiviso con Provider.
class CartModel extends ChangeNotifier {
final List<Product> _items = [];
List<Product> get items => _items;
int get count => _items.length;
void add(Product product) {
_items.add(product);
notifyListeners();
}
}Racchiudi l'intera app in un ChangeNotifierProvider in main, così ogni schermata può accedere al carrello. Il pulsante modifica solo il carrello, quindi usa context.read<CartModel>().add(product). La griglia mostra il conteggio, quindi usa context.watch, che ricostruisce la griglia ogni volta che viene eseguito notifyListeners.
Il conteggio appare sull'icona del carrello come Badge, il piccolo fumetto che le app usano per i messaggi non letti. isLabelVisible: count > 0 lo nasconde quando il carrello è vuoto.
Sfida
DifficileAggiungi a un carrello condiviso:
- importa
package:provider/provider.dart, scrivi ilCartModeldella teoria e racchiudiMyAppin unChangeNotifierProviderche lo crea - nella pagina del prodotto, dopo 32 pixel di spazio, aggiungi un
FilledButton.iconconIcons.add_shopping_carteAdd to cart: aggiunge il prodotto, nasconde qualsiasi messaggio già visualizzato e mostra unoSnackBarcon il testoAdded Backpack to your cart(con il nome del prodotto) - nelle
actionsdell'AppBardella griglia, mostraIcons.shopping_cartin unBadgecon il conteggio, a 24 pixel dal bordo destro
Provalo tu
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
void main() {
runApp(const MyApp());
}
final money = NumberFormat.currency(locale: 'en_US', symbol: '\$');
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.orange),
),
home: const ShopScreen(),
);
}
}
class Product {
const Product({
required this.name,
required this.price,
required this.icon,
required this.color,
required this.description,
});
final String name;
final double price;
final IconData icon;
final MaterialColor color;
final String description;
}
const List<Product> products = [
Product(
name: 'Headphones',
price: 59,
icon: Icons.headphones,
color: Colors.indigo,
description: 'Wireless headphones with 30 hours of battery.',
),
Product(
name: 'Watch',
price: 129,
icon: Icons.watch,
color: Colors.teal,
description: 'A smart watch that counts your steps.',
),
Product(
name: 'Backpack',
price: 45.5,
icon: Icons.backpack,
color: Colors.orange,
description: 'Room for a laptop, a lunch and a jacket.',
),
Product(
name: 'Mug',
price: 12,
icon: Icons.coffee,
color: Colors.brown,
description: 'Holds a big coffee and keeps it warm.',
),
Product(
name: 'Camera',
price: 1299,
icon: Icons.photo_camera,
color: Colors.blueGrey,
description: 'A mirrorless camera for sharp photos.',
),
Product(
name: 'Sneakers',
price: 89.99,
icon: Icons.directions_run,
color: Colors.red,
description: 'Light running shoes for every day.',
),
];
class ShopScreen extends StatelessWidget {
const ShopScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Coddy Shop')),
body: GridView.count(
crossAxisCount: 2,
padding: const EdgeInsets.all(16),
mainAxisSpacing: 12,
crossAxisSpacing: 12,
childAspectRatio: 0.8,
children: [
for (Product product in products) ProductCard(product: product),
],
),
);
}
}
class ProductCard extends StatelessWidget {
const ProductCard({super.key, required this.product});
final Product product;
@override
Widget build(BuildContext context) {
return Card(
clipBehavior: Clip.antiAlias,
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ProductScreen(product: product),
),
);
},
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Container(
width: double.infinity,
alignment: Alignment.center,
color: product.color.shade50,
child: Icon(product.icon, size: 56, color: product.color),
),
),
Padding(
padding: const EdgeInsets.all(12),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
product.name,
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 4),
Text(
money.format(product.price),
style: TextStyle(
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.primary,
),
),
],
),
),
],
),
),
);
}
}
class ProductScreen extends StatelessWidget {
const ProductScreen({super.key, required this.product});
final Product product;
@override
Widget build(BuildContext context) {
final textTheme = Theme.of(context).textTheme;
return Scaffold(
appBar: AppBar(title: Text(product.name)),
body: ListView(
padding: const EdgeInsets.all(24),
children: [
Container(
height: 240,
alignment: Alignment.center,
decoration: BoxDecoration(
color: product.color.shade50,
borderRadius: BorderRadius.circular(24),
),
child: Icon(product.icon, size: 120, color: product.color),
),
const SizedBox(height: 24),
Text(
money.format(product.price),
style: textTheme.headlineSmall?.copyWith(
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.primary,
),
),
const SizedBox(height: 12),
Text(product.description, style: textTheme.bodyLarge),
],
),
);
}
}
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Progetti
1Progetto: Lista delle cose da fare
Lista delle cose da fare: l’elenco delle attivitàLista delle cose da fare: aggiungere un’attività4Progetto: Tracker delle abitudini
Tracker delle abitudini: le tue abitudiniTracker delle abitudini: la settimanaEsercitati da solo: Compilatore Flutter online