Menu
CoddyTech

Tarif Kitabı: Favoriler Sekmesi

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

En sevdiğin tarifleri yeniden bulabiliyorsan kalpler ancak o zaman işe yarar. İkinci bir sekme olan Favorites, yalnızca kırmızı kalp verilen tarifleri gösterir.

Her iki sekmede de aynı görünen bir tarif listesi bulunur; bu yüzden listeyi, gösterilecek tarifleri alan bir yöntem olarak bir kez yaz:

Widget recipeList(List<Recipe> shown) {
  return ListView.builder(...);
}

Favoriler, favorite değeri where koşulunu sağlayan, yani true olan tariflerdir. Sekmenin her setState çağrısından sonra doğru olması için bunları build metodunun başında hesapla. Ardından gövde, sekmeye bağlı olarak recipeList(recipes) veya recipeList(favorites) gösterir.

challenge icon

Görev

Zor

Tarif kitabına sekmeler ekle:

  • ListView.builder öğesini, shown listesini gösteren Widget recipeList(List<Recipe> shown) metoduna taşı
  • İki sekmeli bir NavigationBar ekle: Recipes (Icons.menu_book_outlined, seçiliyken Icons.menu_book) ve Favorites (Icons.star_border, seçiliyken Icons.star); sekmenin index değerini state'te tut
  • Recipes sekmesi tüm tarifleri, Favorites sekmesi ise yalnızca favorileri listeler

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 StatefulWidget {
  const HomeScreen({super.key});

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  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']),
  ];

  @override
  Widget build(BuildContext context) {
    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)),
              );
            },
            trailing: IconButton(
              icon: Icon(
                recipe.favorite ? Icons.favorite : Icons.favorite_border,
                color: recipe.favorite ? Colors.red : null,
              ),
              onPressed: () {
                setState(() {
                  recipe.favorite = !recipe.favorite;
                });
              },
            ),
          );
        },
      ),
    );
  }
}

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;
  bool favorite = false;

  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