Menu
CoddyTech
flag Ar iconالعربيةdown icon

كتاب الوصفات: تبويب المفضلة

جزء من قسم القوائم والشاشات في رحلة Flutter على Coddy. الدرس 32 من 33.

لا تكون القلوب مفيدة إلا إذا استطعت العثور على وصفاتك المفضلة مجددًا. يعرض تبويب ثانٍ، Favorites، الوصفات التي تحمل قلبًا أحمر فقط.

يعرض كلا التبويبين قائمة وصفات تبدو بالطريقة نفسها، لذا اكتب القائمة مرة واحدة، على هيئة دالة تأخذ الوصفات المراد عرضها:

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

الوصفات المفضلة هي الوصفات التي تكون فيها where favorite قيمتها true. حدّدها في أعلى build، لكي يكون التبويب صحيحًا بعد كل setState. ثم يعرض المحتوى recipeList(recipes) أو recipeList(favorites)، حسب التبويب.

challenge icon

التحدي

صعب

أضف علامات تبويب إلى دفتر الوصفات:

  • انقل ListView.builder إلى أسلوب Widget recipeList(List<Recipe> shown) الذي يعرض قائمة shown
  • أضف NavigationBar بعلامتي تبويب: Recipes (Icons.menu_book_outlined وIcons.menu_book عند تحديدها) وFavorites (Icons.star_border وIcons.star عند تحديدها)، مع الاحتفاظ بـ index علامة التبويب في الحالة
  • تعرض علامة التبويب Recipes جميع الوصفات، بينما تعرض علامة التبويب Favorites الوصفات المفضلة فقط

جرّب بنفسك

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 iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس القوائم والشاشات

تدرّب بنفسك: مترجم Flutter عبر الإنترنت