Flutter和Dart系列六:Widget(一)

释放双眼,带上耳机,听听看~!

我们先编写一个简单的demo:


1
2
3
4
5
6
7
8
9
1import 'package:flutter/material.dart';
2
3void main() => runApp(Center(
4   child: Text(
5      'Hello, world!',
6      textDirection: TextDirection.ltr,
7   ),
8));
9
  • import: 和Java中一样,导包

    • function:见系列四
    • 涉及的Widget对象:
  • Center对象:对于子Widget有约束,即它的子Widget是居中的
    * Text:可以类比TextView,第一个参数就是文本内容,textDirection参数指定文本内容是从左到右显示(ltr)还是从右往左(rtl)显示

截图:

  • 我们来看一个更加优雅的demo:

  • 编写我们的main函数:


1
2
3
4
5
6
1void main() {
2    runApp(MaterialApp(
3      home: MyScaffold(),
4    ));
5}
6
  • 将一个MaterialApp对象作为参数传递到了runApp函数中,runApp的作用我们之前的篇章提到过:传入到runApp的widget对象会被作为Widget tree的根节点,并且会显示在屏幕上。
    * MaterialApp对象:它实际上也是一个Widget,它是用来实现Google的Material Design的便捷Widget,即它里面会封装一些其他的widget。一个不恰当的比方就是有点类似Application的主题。
    * home属性:进入程序后显示的第一个页面
    * Dart语言本身相关:

a. 如何创建对象?像Java一样通过new关键字;像Kotlin一样,省略new关键字。这两种方式都ok

b. 关于可选的有名参数(optional named parameter),同样可以参考系列四


1
2
1* 编写MyScaffold类:
2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
1class MyScaffold extends StatelessWidget {
2  @override
3  Widget build(BuildContext context) {
4    return Material(
5      child: Column(
6        children: <Widget>[
7          MyAppBar(
8            title: Text(
9              'Example title',
10              style: Theme.of(context).primaryTextTheme.title,
11            ),
12          ),
13          Expanded(
14            child: Center(
15              child: Text('我是content,我在中间'),
16            ),
17          ),
18        ],
19      ),
20    );
21  }
22}
23
24class MyAppBar extends StatelessWidget {
25  final Widget title;
26
27  MyAppBar({this.title});
28
29  @override
30  Widget build(BuildContext context) {
31    return Container(
32      height: 56.0,
33      padding: const EdgeInsets.symmetric(horizontal: 8.0),
34      decoration: BoxDecoration(color: Colors.blue[500]),
35      child: Row(
36        children: <Widget>[
37          IconButton(
38            icon: Icon(Icons.menu),
39            onPressed: null,
40          ),
41          Expanded(
42            child: title,
43          ),
44          IconButton(icon: Icon(Icons.search), onPressed: null)
45        ],
46      ),
47    );
48  }
49}
50

从MyScaffold中看起:

  • Material:这个就是home页面的根Widget
    * Column:设计理念来自于web中弹性盒子模型,类比到Android中来:就是orientation=vertical的LinearLayout;与之对应的就是Row,它是orientation=horizontal的LinearLayout。
    * Expanded:这个对象可以类比LinearLayout中的weight属性的作用,那么如何设置权重值呢?


1
2
3
4
5
6
7
8
1  class Expanded extends Flexible {
2    const Expanded({
3      Key key,
4      int flex = 1,
5      @required Widget child,
6    }) : super(key: key, flex: flex, fit: FlexFit.tight, child: child);
7  }
8

通过flex来设置,默认是1

MyAppBarLayout中:

  • Container:这个只能勉勉强强比喻成ViewGroup。这里用的属性有height、padding,这俩都好理解;至于这个decoration,可以理解成background.
    * IconButton:类比成ImageButton/ImageView.这里需要注意的是一个onPressed属性,很明显我们可以在这指定点击事件的处理函数.

最终的运行效果为:

 

  • 注意pubspec.yaml文件中


1
2
3
1 flutter:
2   uses-material-design: true
3

这个文件就相当于我们build.gradle文件一样,这里可以指定依赖、版本号等

  • 在demo2中,MyScaffold、MyAppBar,这些都是我们自定义的Widget,实际上这些都有对应的Material组件已经定义好了。请看demo3:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1void main() {
2  runApp(MaterialApp(
3    home: MaterialHome(),
4  ));
5}
6
7class MaterialHome extends StatelessWidget {
8  @override
9  Widget build(BuildContext context) {
10    return Scaffold(
11      appBar: AppBar(
12        leading: IconButton(icon: Icon(Icons.menu), onPressed: null),
13        title: Text("I'm title"),
14        actions: <Widget>[
15          IconButton(
16            icon: Icon(Icons.search),
17            onPressed: null,
18          )
19        ],
20      ),
21      body: Center(
22        child: Text("I'm content and in center"),
23      ),
24      floatingActionButton: FloatingActionButton(
25        onPressed: null,
26        child: Icon(Icons.add),
27      ),
28    );
29  }
30}
31
  • Scaffold:脚手架,它实现了基本Material布局
    • FloatingActionButton:就是我们常见的FAB 运行效果图:

     

  • 下面我想实现对按钮点击的响应: 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
1class MaterialHome extends StatelessWidget {
2  @override
3  Widget build(BuildContext context) {
4    return Scaffold(
5      appBar: AppBar(
6        leading: IconButton(icon: Icon(Icons.menu), onPressed: null),
7        title: Text("I'm title"),
8        actions: <Widget>[
9          IconButton(
10            icon: Icon(Icons.search),
11            onPressed: onSearchClick,
12          )
13        ],
14      ),
15      body: Center(
16        child: Text("I'm content and in center"),
17      ),
18      floatingActionButton: FloatingActionButton(
19        onPressed: onFabClick,
20        child: Icon(Icons.add),
21      ),
22    );
23  }
24
25  void onSearchClick() {
26     // 可以使用print函数输出日志
27    print("search button clicked");
28  }
29
30  void onFabClick() {
31    print("fab  clicked");
32  }
33}
34

注意两个onPressed属性的赋值:直接将我们定义好的函数名传递过去。在Function系列说过,在Dart语言中,所有的函数都是一个对象,它的类型为Function。点击按钮,我们就可以在控制台看到日志输出了,证明我们事件处理函数得到调用了。

参考文献:《Flutter Tutorial》

给TA打赏
共{{data.count}}人
人已打赏
安全技术

C++遍历文件夹

2022-1-11 12:36:11

安全技术

linux安装 python 环境

2022-1-12 12:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索