Menu
CoddyTech

Buku Resep: Tab Favorit

Termasuk bagian List dan Layar dalam perjalanan Flutter di Coddy. Pelajaran 32 dari 33.

Ikon hati hanya berguna jika kamu bisa menemukan resep favoritmu lagi. Tab kedua, Favorites, hanya menampilkan resep dengan ikon hati merah.

Kedua tab menampilkan daftar resep yang terlihat sama, jadi tulis daftarnya sekali saja, sebagai method yang menerima resep untuk ditampilkan:

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

Resep favorit adalah resep yang memenuhi kondisi where, yaitu favorite bernilai true. Tentukan resep tersebut di bagian atas build, agar tab selalu sesuai setelah setiap setState. Body kemudian menampilkan recipeList(recipes) atau recipeList(favorites), bergantung pada tab yang dipilih.

challenge icon

Tantangan

Sulit

Tambahkan tab ke buku resep:

  • pindahkan ListView.builder ke dalam method Widget recipeList(List<Recipe> shown) yang menampilkan shown
  • tambahkan NavigationBar dengan dua tab: Recipes (Icons.menu_book_outlined, Icons.menu_book saat dipilih) dan Favorites (Icons.star_border, Icons.star saat dipilih), lalu simpan index tab dalam state
  • tab Recipes menampilkan semua resep, sedangkan tab Favorites hanya menampilkan resep favorit

Coba sendiri

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 iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di List dan Layar

Latihan sendiri: Compiler Flutter online