Flutter 项目新手向结构简析

文章目录

flutter 面向新手向

flutter 中一切界面层级的东西全部都是 Widget 这句话怎么理解呢?

大到整个应用,小到一个文字控件,全部都是 Widget


一个常规的 Application 图级可能是这样的,当然实际情况下会比这复杂很多

结构图

对应代码和实际情况看一下

为了和图片对应 我把所有的写到一个文件里

 1
 2import 'package:flutter/material.dart';
 3
 4void main() => runApp(new MyApp());
 5
 6class MyApp extends StatelessWidget {
 7  @override
 8  Widget build(BuildContext context) {
 9    return new MaterialApp(
10      title: 'Flutter 结构简析',
11      theme: new ThemeData(
12        primarySwatch: Colors.blue, // 这里是项目的主色调
13      ),
14      home: MyHomePage(),
15    );
16  }
17}
18
19class MyHomePage extends StatefulWidget {
20  @override
21  _MyHomePageState createState() => _MyHomePageState();
22}
23
24class _MyHomePageState extends State<MyHomePage> {
25  @override
26  Widget build(BuildContext context) {
27    return Scaffold(
28      appBar: AppBar(),
29      body: ListView(
30        children: <Widget>[
31          ListTile(title: Text('我是第一个item')),
32          ListTile(title: Text('我是第二个item')),
33        ],
34      ),
35    );
36  }
37}

项目截图

这里的一切皆 widget 的意思就是 Application 是 Widget Page 是 Scaffold 是 Appbar 是 ListView 是 ListTile 也是 Text 也是

组合达到常见的效果

以官方的一个页面为例子

lakes-anno.png


我们来做的话就是整体是一个 Column 或者 ListView 然后子项目是

 1Image
 2Row
 3  Column
 4    Text
 5    Text
 6  Row
 7    Image(Icon)
 8    Text
 9Row
10  Column
11      Row
12        Image
13        Text
14  Column
15  Column
16Text

当然这个是指的主体结构,实际上还会有更多的 接着不看这个链接里的代码,自己撸一个 demo

demo 相关


一阶段 头部图片

第一阶段对应的截图

image.png

代码

 1class TutorialsPage extends StatefulWidget {
 2  @override
 3  _TutorialsPageState createState() => _TutorialsPageState();
 4}
 5
 6class _TutorialsPageState extends State<TutorialsPage> {
 7  @override
 8  Widget build(BuildContext context) {
 9    return Scaffold(
10      body: ListView(
11        children: <Widget>[
12          //为了好分辨,我将内部的4大块分为四个方法
13          _buildHeader(),
14        ],
15      ),
16    );
17  }
18
19  Widget _buildHeader() {
20    // 这里对应的是图片
21    return Image.asset("images/lakes_header.jpg");
22  }
23}

二阶段

第二阶段的截图

image.png

 1
 2class _TutorialsPageState extends State<TutorialsPage> {
 3  @override
 4  Widget build(BuildContext context) {
 5    return Scaffold(
 6      body: ListView(
 7        children: <Widget>[
 8          //为了好分辨,我将内部的4大块分为四个方法
 9          _buildHeader(),
10          Padding(
11            //这里我观察到下面有一个整体的左右边距,所以这里单独抽取了一个padding
12            child: Column(
13              children: <Widget>[
14                _buildSecond(), // 第二部分
15              ],
16            ),
17            padding: const EdgeInsets.only(
18              left: 30.0,
19              right: 30.0,
20            ),
21          ),
22        ],
23      ),
24    );
25  }
26
27  Widget _buildHeader() {
28    // 这里对应的是图片
29    return Image.asset("images/lakes_header.jpg");
30  }
31
32  _buildSecond() {
33    Widget row = Row(
34      children: <Widget>[
35        Expanded(
36          child: Column(
37            children: <Widget>[
38              Text('旅游圣地'),
39              Text('不要钱',style: TextStyle(fontSize: 12.0,color: Colors.grey),),
40            ],
41            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
42            crossAxisAlignment: CrossAxisAlignment.start,
43          ),
44        ),
45        Row(
46          children: <Widget>[
47            Icon(
48              Icons.star,
49              color: Colors.yellow,
50            ),
51            Text('30'),
52          ],
53        ),
54      ],
55    );
56    row = SizedBox(
57      height: 60.0,
58      child: row,
59    );
60    return row;
61  }
62}

第三部分

截图:

第三步

  1
  2/// 对应 https://flutter.io/tutorials/layout/ 的 https://flutter.io/tutorials/layout/images/lakes.jpg 图片
  3class TutorialsPage extends StatefulWidget {
  4  @override
  5  _TutorialsPageState createState() => _TutorialsPageState();
  6}
  7
  8class _TutorialsPageState extends State<TutorialsPage> {
  9  @override
 10  Widget build(BuildContext context) {
 11    return Scaffold(
 12      body: ListView(
 13        children: <Widget>[
 14          //为了好分辨,我将内部的4大块分为四个方法
 15          _buildHeader(),
 16          Padding(
 17            //这里我观察到下面有一个整体的左右边距,所以这里单独抽取了一个padding
 18            child: Column(
 19              children: <Widget>[
 20                _buildSecond(), // 第二部分
 21                _buildThird(), // 第二部分
 22              ],
 23            ),
 24            padding: const EdgeInsets.only(
 25              left: 30.0,
 26              right: 30.0,
 27            ),
 28          ),
 29        ],
 30      ),
 31    );
 32  }
 33
 34  Widget _buildHeader() {
 35    // 这里对应的是图片
 36    return Image.asset("images/lakes_header.jpg");
 37  }
 38
 39  _buildSecond() {
 40    Widget row = Row(
 41      children: <Widget>[
 42        Expanded(
 43          child: Column(
 44            children: <Widget>[
 45              Text('旅游圣地'),
 46              Text('不要钱',style: TextStyle(fontSize: 12.0,color: Colors.grey),),
 47            ],
 48            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
 49            crossAxisAlignment: CrossAxisAlignment.start,
 50          ),
 51        ),
 52        Row(
 53          children: <Widget>[
 54            Icon(
 55              Icons.star,
 56              color: Colors.yellow,
 57            ),
 58            Text('30'),
 59          ],
 60        ),
 61      ],
 62    );
 63    row = SizedBox(
 64      height: 60.0,
 65      child: row,
 66    );
 67    return row;
 68  }
 69
 70  _buildThird() {
 71    Widget buildItem(IconData iconData, String text) {
 72      return Expanded(
 73        child: SizedBox(
 74          height: 50.0,
 75          child: Column(
 76            children: <Widget>[
 77              Icon(
 78                iconData,
 79                color: Colors.blue,
 80              ),
 81              Text(
 82                text,
 83                style: TextStyle(color: Colors.blue),
 84              ),
 85            ],
 86            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
 87          ),
 88        ),
 89      );
 90    }
 91
 92    return Row(
 93      children: <Widget>[
 94        buildItem(Icons.phone, '呼叫'),
 95        buildItem(Icons.room, '导航'),
 96        buildItem(Icons.share, '分享'),
 97      ],
 98    );
 99  }
100}

第四部分

image.png

  1
  2/// 对应 https://flutter.io/tutorials/layout/ 的 https://flutter.io/tutorials/layout/images/lakes.jpg 图片
  3class TutorialsPage extends StatefulWidget {
  4  @override
  5  _TutorialsPageState createState() => _TutorialsPageState();
  6}
  7
  8class _TutorialsPageState extends State<TutorialsPage> {
  9  @override
 10  Widget build(BuildContext context) {
 11    return Scaffold(
 12      body: ListView(
 13        children: <Widget>[
 14          //为了好分辨,我将内部的4大块分为四个方法
 15          _buildHeader(),
 16          Padding(
 17            //这里我观察到下面有一个整体的左右边距,所以这里单独抽取了一个padding
 18            child: Column(
 19              children: <Widget>[
 20                _buildSecond(), // 第二部分
 21                _buildThird(),
 22                _buildFourth(),
 23              ],
 24            ),
 25            padding: const EdgeInsets.only(
 26              left: 30.0,
 27              right: 30.0,
 28            ),
 29          ),
 30        ],
 31      ),
 32    );
 33  }
 34
 35  Widget _buildHeader() {
 36    // 这里对应的是图片
 37    return Image.asset("images/lakes_header.jpg");
 38  }
 39
 40  _buildSecond() {
 41    Widget row = Row(
 42      children: <Widget>[
 43        Expanded(
 44          child: Column(
 45            children: <Widget>[
 46              Text('旅游圣地'),
 47              Text(
 48                '不要钱',
 49                style: TextStyle(fontSize: 12.0, color: Colors.grey),
 50              ),
 51            ],
 52            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
 53            crossAxisAlignment: CrossAxisAlignment.start,
 54          ),
 55        ),
 56        Row(
 57          children: <Widget>[
 58            Icon(
 59              Icons.star,
 60              color: Colors.yellow,
 61            ),
 62            Text('30'),
 63          ],
 64        ),
 65      ],
 66    );
 67    row = SizedBox(
 68      height: 60.0,
 69      child: row,
 70    );
 71    return row;
 72  }
 73
 74  _buildThird() {
 75    Widget buildItem(IconData iconData, String text) {
 76      return Expanded(
 77        child: SizedBox(
 78          height: 50.0,
 79          child: Column(
 80            children: <Widget>[
 81              Icon(
 82                iconData,
 83                color: Colors.blue,
 84              ),
 85              Text(
 86                text,
 87                style: TextStyle(color: Colors.blue),
 88              ),
 89            ],
 90            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
 91          ),
 92        ),
 93      );
 94    }
 95
 96    return Row(
 97      children: <Widget>[
 98        buildItem(Icons.phone, '呼叫'),
 99        buildItem(Icons.room, '导航'),
100        buildItem(Icons.share, '分享'),
101      ],
102    );
103  }
104
105  _buildFourth() {
106    return Padding(
107      padding: const EdgeInsets.all(8.0),
108      child: Text(
109        '这个旅游地方我也不知道是什么地方,有什么流弊的,不过看起来还不错.\n\n'
110            '这篇文章就到这里基本也没啥说的了,这个是第四部分,我就把内容直接放在Widget里面了,感谢观看,后面我可能会出一个简易的FAQ,专门写一些小白问题☺☺☺☺☺',
111        style: TextStyle(
112          fontSize: 13.0,
113        ),
114      ),
115    );
116  }
117}