第二章:Hello,Flutter(六)

本文介绍了如何在Flutter应用中从简单Text跳转升级为实现Recipe Detail页面,添加菜谱原料列表,展示了从原料实体类创建到展示的完整过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Flutter-从入门到放弃(目录,持续更新中)

创建食谱详情页

APP之前的点击跳转目标页只是也给简单的Text,甚至在IOS上都无法返回,现在我们创建一个真正的食谱详情页来替换掉它.
在lib文件夹下创建一个dart文件,recipe_detail.dart作为我们的食谱详情页,代码如下:

import 'package:flutter/material.dart';
import 'package:recipes/recipe.dart';

class RecipeDetail extends StatefulWidget {
  final Recipe recipe;

  const RecipeDetail({Key? key, required this.recipe}) : super(key: key);

  @override
  State<StatefulWidget> createState() {
    return _RecipeDetailState();
  }
}

class _RecipeDetailState extends State<RecipeDetail> {
  @override
  Widget build(BuildContext context) {
    //1.Scaffold 构成页面的基本框架,由其他Widget组成UI
    return Scaffold(
      appBar: AppBar(title: Text(widget.recipe.label)),
      //2.SafeArea 可以避免APP的UI太过靠近系统UI,干扰与系统的交互
      body: SafeArea(
        child: Column(
          children: <Widget>[
            //3.SizedBox 固定了高度,宽度可调整以适应图片
            SizedBox(
              height: 300,
              width: double.infinity,
              child: Image(
                image: AssetImage(widget.recipe.imageUrl),
              ),
            ),
            //4. 此处作为一个间距来分割图片和下方的文字
            const SizedBox(
              height: 4,
            ),
            //5. 仅仅定义了字体大小
            Text(
              widget.recipe.label,
              style: const TextStyle(fontSize: 18),
            )
            // TODO: Add Expanded
          // TODO: Add Slider() here
          ],
        ),
      ),
    );
  }
}

main.dart中导入上面的recipe_detail.dart,然后在点击事件中标注
**//TODO: Replace return with return RecipeDetail()**的地方替换为

return RecipeDetail(recipe: Recipe.samples[index])

此时hot reload已经无法体现我们的修改了,我们直接运行APP,点击列表进入详情页,效果如下:
在这里插入图片描述

菜谱原料

为了丰富一下菜谱详情页面,我们添加一下菜谱需要的原料的数据,我们先建立一个原料的实体类,包括其名称,数量及计量单位。在recipe.dart中,添加以下代码:

class Ingredient {
  double quantity;
  String measure;
  String name;
  Ingredient(
      this.quantity,
      this.measure,
      this.name,
      );
}

然后在Recipe类中添加以下代码,分别是该菜谱的分量可供几人食用以及需要的原料的列表:

int servings;
List<Ingredient> ingredients;

当然,Recipe类的构造函数也需要加上这两个属性:


  Recipe(this.label, this.imageUrl, this.servings, this.ingredients);

同样的,供测试用的samples列表也需要相应的加上这些属性。

 //测试用数据
  static List<Recipe> samples = [
    Recipe(
      'Spaghetti and Meatballs',
      'assets/2126711929_ef763de2b3_w.jpg',
      4,
      [
        Ingredient(
          1,
          'box',
          'Spaghetti',
        ),
        Ingredient(
          4,
          '',
          'Frozen Meatballs',
        ),
        Ingredient(
          0.5,
          'jar',
          'sauce',
        ),
      ],
    ),
    Recipe(
      'Tomato Soup',
      'assets/27729023535_a57606c1be.jpg',
      2,
      [
        Ingredient(
          1,
          'can',
          'Tomato Soup',
        ),
      ],
    ),
    Recipe(
      'Grilled Cheese',
      'assets/3187380632_5056654a19_b.jpg',
      1,
      [
        Ingredient(
          2,
          'slices',
          'Cheese',
        ),
        Ingredient(
          2,
          'slices',
          'Bread',
        ),
      ],
    ),
    Recipe(
      'Chocolate Chip Cookies',
      'assets/15992102771_b92f4cc00a_b.jpg',
      24,
      [
        Ingredient(
          4,
          'cups',
          'flour',
        ),
        Ingredient(
          2,
          'cups',
          'sugar',
        ),
        Ingredient(
          0.5,
          'cups',
          'chocolate chips',
        ),
      ],
    ),
    Recipe(
      'Taco Salad',
      'assets/8533381643_a31a99e8a6_c.jpg',
      1,
      [
        Ingredient(
          4,
          'oz',
          'nachos',
        ),
        Ingredient(
          3,
          'oz',
          'taco meat',
        ),
        Ingredient(
          0.5,
          'cup',
          'cheese',
        ),
        Ingredient(
          0.25,
          'cup',
          'chopped tomatoes',
        ),
      ],
    ),
    Recipe(
      'Hawaiian Pizza',
      'assets/15452035777_294cefced5_c.jpg',
      4,
      [
        Ingredient(
          1,
          'item',
          'pizza',
        ),
        Ingredient(
          1,
          'cup',
          'pineapple',
        ),
        Ingredient(
          8,
          'oz',
          'ham',
        ),
      ],
    ),
  ];
}

展示原料

菜谱原料的数据准备好之后,我们就可以在菜谱详情页中展示这些原料了。在 recipe_detail.dart中,我们找到之前的TODO: Add Expanded替换为以下代码:

 //6.Expanded 添加一个列表来展示原料
            Expanded(
              child: ListView.builder(
                padding: const EdgeInsets.all(7.0),
                itemCount: widget.recipe.ingredients.length,
                itemBuilder: (BuildContext context, int index) {
                  final ingredient = widget.recipe.ingredients[index];
                  // TODO: Add ingredient.quantity
                  return Text(
                      '${ingredient.quantity} ${ingredient.measure} ${ingredient.name}');
                },
              ),
            ),

注意,这段代码添加在了Column的children数组里,不要加错位置了,效果如下:在这里插入图片描述
ok,可以看到原料的列表了,后面我们将继续添加一些交互进来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值