Menu
CoddyTech

Tarif Kitabı: Favoriler

Coddy'nin Flutter Journey'sinin Listeler ve Ekranlar bölümünün bir parçası. Ders 31 / 33.

Bazı yemek tariflerini her hafta pişirirsin. Her satırın sonundaki bir kalp, favoriyi işaretler: favori değilse içi boş bir kalp, favoriyse kırmızı ve dolu bir kalp.

Bir tarifin favori olup olmaması tarifin bir parçasıdır, bu yüzden bir alan olur. Diğerlerinden farklı olarak değiştiği için final değildir ve başlangıç değeri false olur:

bool favorite = false;

Değişen veriler setState gerektirir, bu nedenle HomeScreen bir StatefulWidget olur. Tarifler build içinden çıkıp State sınıfına taşınır: build içinde oluşturulan bir liste her setState çağrısında yeniden oluşturulur ve bütün kalplerin içi boşalır.

Kalp bir IconButton'dır. Simgesi, ? : ile dolu ya da boş kalbi seçer; düğmeye basıldığında alanın değeri tersine çevrilir: recipe.favorite = !recipe.favorite.

challenge icon

Görev

Zor

Her tarife bir favori kalbi ekle:

  • Recipe sınıfına bool favorite = false; alanını ekle
  • HomeScreen'i bir StatefulWidget'a dönüştür ve tarifler listesini State sınıfına taşı
  • Her kutucuğa, Icons.favorite_border gösteren bir trailing: IconButton ekle; tarif favoriyse bunun yerine kırmızı bir Icons.favorite göster. Düğmeye basıldığında favorite değerini tersine çevir

Kendin dene

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

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

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

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

  @override
  Widget build(BuildContext context) {
    final List<Recipe> recipes = [
      Recipe(name: 'Pancakes', minutes: 20, ingredients: ['Flour', 'Eggs', 'Milk', 'Butter']),
      Recipe(name: 'Tomato Soup', minutes: 35, ingredients: ['Tomatoes', 'Onion', 'Garlic', 'Olive oil']),
      Recipe(name: 'Guacamole', minutes: 10, ingredients: ['Avocados', 'Lime', 'Onion', 'Salt']),
      Recipe(name: 'Fried Rice', minutes: 25, ingredients: ['Rice', 'Eggs', 'Peas', 'Soy sauce']),
    ];
    return Scaffold(
      appBar: AppBar(title: const Text('Recipe Book')),
      body: ListView.builder(
        itemCount: recipes.length,
        itemBuilder: (context, index) {
          final Recipe recipe = recipes[index];
          return ListTile(
            leading: const Icon(Icons.restaurant_menu),
            title: Text(recipe.name),
            subtitle: Text('${recipe.minutes} min'),
            onTap: () {
              Navigator.push(
                context,
                MaterialPageRoute(builder: (context) => RecipeScreen(recipe: recipe)),
              );
            },
          );
        },
      ),
    );
  }
}

class RecipeScreen extends StatelessWidget {
  const RecipeScreen({super.key, required this.recipe});

  final Recipe recipe;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(recipe.name)),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: [
          Text('Ready in ${recipe.minutes} minutes', style: const TextStyle(fontSize: 18)),
          const SizedBox(height: 24),
          const Text('Ingredients', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
          for (String ingredient in recipe.ingredients)
            ListTile(
              leading: const Icon(Icons.check_circle_outline),
              title: Text(ingredient),
            ),
        ],
      ),
    );
  }
}

class Recipe {
  final String name;
  final int minutes;
  final List<String> ingredients;

  Recipe({required this.name, required this.minutes, required this.ingredients});
}
quiz iconKendini test et

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

Listeler ve Ekranlar bölümündeki tüm dersler

Kendi başına pratik yap: Online Flutter derleyicisi