创建食谱详情页
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,可以看到原料的列表了,后面我们将继续添加一些交互进来。