万事皆 Widget
Flutter 的核心思想是用 widget 来构建你的 UI 界面。 Widget 描述了在当前的配置和状态下视图所应该呈现的样子。当 widget 的状态改变时,它会重新构建其描述(展示的 UI),框架则会对比前后变化的不同,以确定底层渲染树从一个状态转换到下一个状态所需的最小更改。
我自己是做iOS开发的,这里就以iOS为例说明。
在 iOS 中, UI 中创建的大部分视图都是 UIView 的实例。而在构造布局时,这些视图也可以作为其他视图的容器。
在 Flutter 中,同 UIView 能够进行类比的就是 Widget 了。但 Widget 和 iOS 里的视图并不能同等对待,不过想要了解 Flutter 的工作原理时,可以把它理解为“声明和构造 UI 的方法”。
然而,Widget 和 UIView 还是有着相当一部分区别的。首先,widget 拥有着不同的生命周期:整个生命周期内它是不可变的,且只能够存活到被修改的时候。一旦 widget 实例或者它的状态发生了改变, Flutter 框架就会创建一个新的由 Widget 实例构造而成的树状结构。而在 iOS 里,修改一个视图并不会导致它重新创建实例,它作为一个可变对象,只会绘制一次,只有在发生 setNeedsDisplay() 调用之后才会发生重绘。另外,Flutter 的 widget 是很轻量的,一部分原因就是源于它的不可变特性。因为它并不是视图,也不直接绘制任何内容,而是作为对 UI 及其特性的一种描述,而被“注入”到视图中去。
在 iOS 可以直接对视图进行修改。但是在 Flutter 中,widget 都是不可变的,所以也不能够直接对其修改。所以,你必须通过修改 widget 的 state 来达到更新视图的目的。Flutter 包含 Stateful widget 和 Stateless widget 的概念。
和字面意思相同,StatelessWidget 就是一个没有绑定状态的 widget。当某个 widget 不需要依赖任何别的初始配置来对这个 widget 进行描述时, StatelessWidgets 会是很有用的。举个例子,在 iOS 中,你需要把 logo 当作 image 并将它放置在 UIImageView 中,如果在运行时这个 logo 不会发生变化,那么对应 Flutter 中你应该使用 StatelessWidget。
而 StatefulWidget 中有一个 State 对象,它用来存储一些状态的信息,并在整个生命周期内保持不变。一旦改变,Flutter 框架就会创建一个新的由 Widget 实例构造而成的树状结构。
Flutter 自带了一套强大的基础 widgets,下面列举一些常用的:
Text widget 可以用来在应用内创建带样式的文本。
这两个 flex widgets 可以让你在水平 (Row) 和垂直(Column) 方向创建灵活的布局。它是基于 web 的 flexbox 布局模型设计的。
Stack widget 不是线性(水平或垂直)定位的,而是按照绘制顺序将 widget 堆叠在一起。你可以用 Positioned widget 作为Stack 的子 widget,以相对于 Stack 的上,右,下,左来定位它们。 Stack 是基于 Web 中的绝对位置布局模型设计的。
Container widget 可以用来创建一个可见的矩形元素。 Container 可以使用 BoxDecoration 来进行装饰,如背景,边框,或阴影等。 Container 还可以设置外边距、内边距和尺寸的约束条件等。另外,Container可以使用矩阵在三维空间进行转换。