页面简单分析

首先我们观察下,发现页面的是一个ListView, 但是在写的时候尽量使用Container来包装一层,这样可以增加拓展性,类比iOS中的TabView.

接着上篇,那我们直接在发现页面修改:首先在AppBar新增一个centerTitle这个属性专门为安卓设计的,其次默认的AppBar是底部边缘是有一条线的,我们使用elevation = 0可以隐藏这条线。

  1. appBar: AppBar(
  2. centerTitle: true, // 这个属性专为安卓设计
  3. elevation: 0,
  4. title: Text('发现'),
  5. )

修改body为Container包装的ListView, 现在的代码成了这样

  1. class _DiscoverPageState extends State<DiscoverPage> {
  2. @override
  3. Widget build(BuildContext context) {
  4. return Scaffold(
  5. appBar: AppBar(
  6. centerTitle: true,
  7. elevation: 0,
  8. title: Text('发现'),
  9. ),
  10. body: Container(
  11. child: ListView(),
  12. ),
  13. );
  14. }
  15. }

定制Cell

好了,接着来自定义cell。首先默认先写一个无状态的Widget,后面如果涉及到状态会变更的话再修改。分析:

  • 暴露四个参数title titleImageName subTitle subImageName,我们可以使用下面四个来作为参数创建一个构造函数
  • 整体是个Row分成左右两块,在主轴左右两侧分开MainAxisAlignment.spaceBetween
  • 左右两块也是一个子Row.
  • sub属性是可选的所以语法可以使用三目运算符
  • 左边的图片和文字之间的间距可以使用SizedBox(width: 15)

所以此时的代码是这样的:

  1. import 'package:flutter/material.dart';
  2. class DiscoverCell extends StatelessWidget {
  3. final String title;
  4. final String titleImageName;
  5. final String? subTitle;
  6. final String? subImageName;
  7. DiscoverCell({
  8. required this.title,
  9. required this.titleImageName,
  10. this.subTitle,
  11. this.subImageName,
  12. }) : assert(title != null, 'title不能为空'),
  13. assert(titleImageName != null, 'titleImageName不能为空');
  14. @override
  15. Widget build(BuildContext context) {
  16. return Container(
  17. child: Row(
  18. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  19. children: [
  20. Container(
  21. padding: EdgeInsets.all(10),
  22. child: Row(
  23. children: [
  24. Image(
  25. image: AssetImage(titleImageName),
  26. width: 20,
  27. ),
  28. SizedBox(width: 15),
  29. Text(title)
  30. ],
  31. )),
  32. Container(
  33. padding: EdgeInsets.all(10),
  34. child: Row(
  35. children: [
  36. subTitle != null ? Text(subTitle!) : Text(''),
  37. subImageName != null ? Image.asset(subImageName!) : Container(),
  38. Image(
  39. image: AssetImage('images/icon_right.png'),
  40. width: 15,
  41. )
  42. ],
  43. ))
  44. ],
  45. ),
  46. );
  47. }
  48. }

回到DiscoverPage页面,LIstView的Chidren设置上面定制的Widget,运行:

image.png

分割线

分割线可以使用下面的这个代码,Row布局分成两块针对性的设置颜色即可。

  1. Row(children: [
  2. Container(width: 50, height: 0.5, color: Colors.white),
  3. Container(height: 0.5,color: Colors.grey)])

image.png

push跳转

点击cell的时候我们希望跳转到一个新的子页面,此时修改下cell的Build的方法.。引出了GestureDetector这个新的Widget,里面有一个onTap方法,我们在这里处理点击事件。

  • onTap
  • onTapDown:点下来
  • onTapCancel:离开了

image.png
这里的Navigator._of_(context).push的是一个Route<T>的子类MaterialPageRoute。而这个函数的构造需要一个bulider
image.png
继续点击发现是这个声明的类型:

  1. final WidgetBuilder builder;
  2. typedef WidgetBuilder = Widget Function(BuildContext context);

所以也就是一个含有BuildContext context参数的一个函数。

  1. Navigator.of(context).push(MaterialPageRoute(
  2. builder: (BuildContext context) =>
  3. DiscoverChildPage(title: title)));

此时的DiscoverChildPage是一个新的子页面,需要一个参数title来作为appBar的title展示。

  1. import 'package:flutter/material.dart';
  2. class DiscoverChildPage extends StatelessWidget {
  3. final String title;
  4. DiscoverChildPage({required this.title});
  5. @override
  6. Widget build(BuildContext context) {
  7. return Scaffold(
  8. appBar: AppBar(
  9. title: Text(title),
  10. ),
  11. body: Center(
  12. child: Text(title),
  13. ),
  14. );
  15. }
  16. }

image.png

无状态修改成有状态

把这里的cell从无状态修改成有状态的:
class _DiscoverCellState extends State<DiscoverCell>{}
在这里无法访问DiscoverCell里面的成员,此时可以使用widget.title�