3.flutter开发基础-Widget组件

1.Widge组件分类

在flutter中,所有UI元素都是widget组件,除了我们常见的button,Image这些可见元素,布局也是组件,甚至文本格式控制也是组件。这里我们先简单讲解一下我们通常概念的上的UI控件。在flutter中组件有两种:有状态组件和无状态组件。

  • 无状态组件(stateless widget),无状态组件不提供可变状态维护,无状态组件仅根据其属性来渲染,
  • 有状态组件(stateful Widget),组件自己维护状态,组件渲染由SetState方法调用,更具state的变化差异来更新渲染。所有的stateful widget都是建立在stateless widget上的。
    这里我们先讲解stateless widget, flutter中的stateless widget主要分为这几类:
  • Visual Base Elemet, 可视基础元素比如:Text,Image, Icon
  • Layout: 布局元素,flutter比较特别一点,它把布局也作为页面元素,这样做的主要目的是可以简化布局计算。以前UI做Layout通常通过Layout引擎根据预定的约束来进行计算, 计算过程实际上是做多元方程式求解,元素越多求解计算就越慢,参考:从 Auto Layout 的布局算法谈性能
    。而flutter将layout也作为页面元素,使得布局在局部范围就可以求解。Layout元素有:Row,Column,Center,Align,Padding等
  • Painting and Effect Widgets& Animation and Motion
    ,绘制和效果组件。绘制和效果组件主要是负责可视元素的装饰效果,比如实现边框(DecoratedBox),实现半透明(Opacity),位移旋转变换(Transform),Animation and Motion是比较特殊的效果组件,用于实现动画效果
  • Container&compound element 大多数我们常用的各种控件都是由基础元素和布局组合而成的,比如button由Text,Image,DecoratedBox等元素组成
  • Interaction Model Widgets, 这个是专门处理事件响应的组件,用于响应用户的操作

2.让我们来创建Hello World

首先我们先来写一个最基本的flutter应用吧。

1.在适当的目录执行:

flutter init -o my_hello_world_app

2.替换my_hello_world_app/lib/main.dart文件中的内容:

import 'package:flutter/material.dart';
void main() => runApp(new Center(child: new Text('Hello, world!')));

3.在my_hello_world_app目录下执行:

flutter start

4.你将会在手机上看到:


这里写图片描述

如果你能一切顺利的来到这里,那么恭喜你,你已经成功使用flutter开发了一个android的应用,虽然这个应用看上去比较单一。

main方法是这个应用的入口,要运行一个应用的话需要使用runApp方法,它接收一个Widget控件作为参数,并且把这个控件作为控件树的根节点。在我们这个例子里,控件树里有两个控件,Center控件和它的子节点Text。通常情况下框架会强制将根控件充满整个屏幕,所以相对的Text控件就以屏幕为中心了。

重要概念:
在编写flutter应用的时候,通常情况下需要自定义组件,这些组件继承自StatelessComponentStatefulComponent,选择要继承哪一个取决于这个组件是否需要管理状态和配置。一个组件的主要工作就是实现build方法,这个方法用来反应该组件在其他组件中的表现形式。最后底层框架会统一从上到下调用build方法直至渲染树的最底层。

基本控件

flutter提供了一套完备的基本控件,最常用的有如下几个:

  • Text :Text提供了一个用来显示文本的一次性控件(即无状态)。
  • Row, Column:这两个控件用来显示水平或垂直方向上的多个组件,并且是可伸缩的。
  • Stack:可以将多个组件以一定的顺序排列,可以使用Positioned控件来指定组件在Stack中的顺序。
  • Container: 是一个可视化的矩形控件,它可以使用BoxDecoration来进行外观装饰,装饰内容可以是背景,边框和阴影等。Container也有外边距,内边距等属性,也可以约束自身的大小,另外值得一提的是Container还可以利用矩阵在三维控件内做转换。

下面结合一些基本的控件来自定义我们的组件并构建应用:
修改main.dart代码如下

import 'package:flutter/material.dart';

class MyToolBar extends StatelessComponent { //(3)
  MyToolBar({ this.title });

  final Widget title; //(6)

  Widget build(BuildContext context) {
    return new Container(
      height: 56.0,
      padding: const EdgeDims.symmetric(horizontal: 8.0),
      decoration: new BoxDecoration(
        backgroundColor: Colors.blue[500]
      ),
      child: new Row([
        new IconButton(icon: 'navigation/menu'),
        new Flexible(child: title),
        new IconButton(icon: 'action/search'),
      ])
    );
  }
}

class MyScaffold extends StatelessComponent { //(4)
  Widget build(BuildContext context) {
    return new Material(
      child: new Column([
        new MyToolBar(
          title: new Text('Example title', style: Typography.white.title)
        ),
        new Flexible(
          child: new Center(
            child: new Text('Hello, world!')
          )
        )
      ])
    );
  }
}

void main() {
  runApp(new MaterialApp( //(1)
    title: 'My app',
    routes: <String, RouteBuilder>{ //(2)
      '/': (RouteArguments args) => new MyScaffold() //(5)
    }
  ));
}

同时确保flutter.yaml文件内容如下:

name: my_app
material-design-icons:
  - name: action/search
  - name: navigation/menu

我们先来运行一下这个应用:


这里写图片描述

恭喜你,顺利存活。
代码解释如下:

  • (1)处的MaterialApp是整个应用的主题控件,一般我们自定义的组件要写在它里面才会有Material的主题风格
  • (2)处的routes的作用是页面导航作用,/表示应用打开的第一个页面。
  • (3)处的MyToolBar是我们自定义的一个无状态组件,通过build方法,我们可以看出其最外层是一个Container控件,控件高为56dp,左右内边距8dp,它由一个BoxDecoration做修饰,修饰内容是将背景颜色改为Colors.blue[500]这种颜色。Container的内部是一个Row,Row的两端分别是一个图标按钮,中间是另一个控件Flexible,它的作用是填充掉Row的剩余部分。在Flexible中传入的是title这个内部字段。
  • (4)处的MyScaffold组件将其子节点用垂直的方式组织起来,在Column的第一个位置是我们自定义的MyToolBar,在构造MyToolBar的时候将一个Text控件作为它的命名可选参数title的值传递进去。在Column的第二个位置是一个Flexible用来填充剩余的空间,在Flexible里面放置了一个Center组件,Center组件里则是一个Text用来显示“Hello,World”。
  • (5)处表示这个应用的第一个见面就是MyScaffold

这种flutter这种层层包裹的感觉就是前面提到的组件外构建UI一小部分含义,眼尖的同学可能已经看到(6)处的title使用的是final修饰符,这里要说明一下继承自StatelessComponent的组件,如内部有配置,属性或状态的统一需要使用final修饰符,表示这个组件本身自己是无状态的,需要依赖它外部的其他组件。这也是'组件外构建UI'最重要的含义所在

Material应用

上面那个应用我们使用自己的组件进行应用开发,发现应用整体美观度不高。是因为flutter中应用界面会撑满整个屏幕,所以有一部分内容可能会被状态栏挡住。其实flutter提供了一系列的控件供开发人员开发Material风格的应用,这之中就有MaterialAppScaffoldToolBarFloatingActionButton等。下面看一个使用了这些控件的例子:

修改main.dart内容如下:

import 'package:flutter/material.dart';

void main() {
  runApp(new MaterialApp(
      title: 'Flutter Tutorial',
      routes: {'/': (RouteArguments args) => new TutorialHome()}));
}

class TutorialHome extends StatelessComponent {
  Widget build(BuildContext context) {
    return new Scaffold(
        toolBar: new ToolBar(
            left: new IconButton(icon: 'navigation/menu'),
            center: new Text('Example title'),
            right: [new IconButton(icon: 'action/search')]),
        body: new Center(child: new Text('Hello, world!')),
        floatingActionButton:
            new FloatingActionButton(child: new Icon(icon: 'content/add')));
  }
}

修改flutter.yaml文件内容如下:

name: my_app
material-design-icons:
  - name: action/search
  - name: content/add
  - name: navigation/menu

运行结果如下:


这里写图片描述

现在我们的应用看起来是不是更像是一个Material Design的应用了?我们使用的ScaffoldToolBar让ToolBar自带了阴影并且字体风格有有了调整。另外还加上了FloatingActionButton

总结

本文主要讲解flutter中的组件分类,对如何创建简单Stateless组件进行了演示

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • 以下内容基本翻译自A Tour of the Flutter Widget Framework,翻译的可能并不完全...
    INeil阅读 10,259评论 0 4
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,398评论 25 707
  • 2017年11月5号 星期天 天气晴 每次回老家我都帮婆婆打扫卫生,料理家务忙的不可开交,孩子们玩的不亦乐乎! 中...
    松鸽阅读 133评论 0 0
  • 11 搀起芹子的是小英。 冬冬,也早放了自己的白菜,跳到沟渠下面,把那块烂白菜举了上来。人,也爬了出来,站在她俩身...
    筱昀阅读 534评论 21 27
  • 说的话像个大哑巴,一口一个爪牙 没有人说的话,是一个大哑巴 我是一个哑巴 能说话的哑巴 能漏出牙齿的哑巴 我不说话...
    导演张升志阅读 452评论 0 0