由上面的架构图可以看出来,flutter最上层是google 的纸墨设计Material Design(MaterialApp)组件,关于Material Design设计理念大家可以去官网安利一下啊material.io
在MaterialApp下面是所有组件的基类Widget,而在Widget的上层是statelessWdiget(无状态组件)、statefulWidget(有状态组件)和InheritedWidget(可以向子类View树种传递信息),包括我们在上篇文章中用到的Scaffold、Center、Text都是statelessWdiget、statefulWidget的子类。
开始之前,我们需要知道一些名词的含义和作用,在这里不懂的也没有关系,逐渐往后面看,往后面使用后,会有越来越清晰的理解。
-
MaterialApp
是我们app开发中常用的符合MaterialApp Design设计理念的入口Widget。
-
StatelessWidget
StatelessWidget是非动态的,它不依赖于除了传入数据以外的任何其他数据,这意味着改变其显示的唯一方式,就是改变传入其构造函数的参数。比如Text,Button,Icon这些控件。
-
StatefulWidget
StatefulWidget是动态的,他们允许我们创建一个能动随时间改变内容的widget,并且不依赖于其初始化时被传入的静态状态,可以随着用户的输入,各种形式的异步回包或其他形式的状态变化而变化。比如Image,CheckBox,Form这些控件。
-
Scaffold
Scaffold 翻译过来就是脚手架的意思,它实现了基本的 Material Design 可视化布局结构。简单的说,Scaffold就是一个提供 Material Design 设计中基本布局的 widget。
const Scaffold({
Key key,
this.appBar, // 标题栏
this.body, // 用于显示当前界面主要内容的Widget
this.floatingActionButton, // 一个悬浮在body上的按钮,默认显示在右下角
this.floatingActionButtonLocation, // 用于设置floatingActionButton显示的位置
this.floatingActionButtonAnimator, // floatingActionButton移动到一个新的位置时的动画
this.persistentFooterButtons, // 多状态按钮
this.drawer, // 左侧的抽屉菜单
this.endDrawer, // 右'侧的抽屉菜单
this.bottomNavigationBar,// 底部导航栏。
this.bottomSheet, // 显示在底部的工具栏
this.backgroundColor,// 内容的背景颜色
this.resizeToAvoidBottomPadding = true, // 控制界面内容 body 是否重新布局来避免底部被覆盖,比如当键盘显示的时候,重新布局避免被键盘盖住内容。
this.primary = true,// Scaffold是否显示在页面的顶部
})
一个 MaterialApp 由多个 Scalfold 页面组成,每个 Scalfold 的主要结构如下:
AppBar:顶部导航栏
body:中间内容体
BottomNavigationBar:底部导航栏
-
Container
它是一个结合了绘制(painting)、定位(positioning)以及尺寸(sizing)widget的widget。
Container({
Key key,
this.alignment,
this.padding,
Color color,
Decoration decoration,
this.foregroundDecoration,
double width,
double height,
BoxConstraints constraints,
this.margin,
this.transform,
this.child,
})
alignment:控制child的对齐方式
decoration:绘制在child后面的装饰
-
padding/margin
控件加入内/外边距。属性如下:
EdgeInsets.all(12),// 指定四个方向相同的值
EdgeInsets.fromLTRB(10, 20, 30, 40),// 分别指定四个方向的值
EdgeInsets.only(left: 10,right: 30),// 指定任意个方向的值EdgeInsets.symmetric(vertical: 10,horizontal: 50),//指定水平(left right)或垂直方向(top,bottom)的值。
-
线性布局Row、Column
Row和Column分别是Flutter中的水平和垂直布局,对应Android里面的LinearLayout的水平垂直方向布局。
MainAxisAlignment (主轴)属性:
enum MainAxisAlignment {
//将子控件放在主轴的开始位置
start,
//将子控件放在主轴的结束位置
end,
//将子控件放在主轴的中间位置
center,
//将主轴空白位置进行均分,排列子元素,手尾没有空隙
spaceBetween,
//将主轴空白区域均分,使中间各个子控件间距相等,首尾子控件间距为中间子控件间距的一半
spaceAround,
//将主轴空白区域均分,使各个子控件间距相等
spaceEvenly,
}
CrossAxisAlignment(交叉轴)属性:
enum CrossAxisAlignment {
//将子控件放在交叉轴的起始位置
start,
//将子控件放在交叉轴的结束位置
end,
//将子控件放在交叉轴的中间位置
center,
//使子控件填满交叉轴
stretch,
//将子控件放在交叉轴的上,并且与基线相匹配(不常用)
baseline,
}
配合Expanded使用,使Expanded中的child充满空白区域。Expanded组件必须用在Row、Column、Flex内。
Expanded(
flex: 1,
child: Text(""),
)
属性:
crossAxisAlignment:交叉轴子组件对齐方式
mainAxisAlignment:主轴子组件排列方式
mainAxisSize:Main 轴大小,相当于match_parent,wrap_content
verticalDirection:从下向上或从上向下摆放子组件
效果:
-
相对布局Stack
Stack 这个是Flutter中布局用到的组件,跟Android中FrameLayout或RelativeLayout很像。是一个在布局中使用相当频繁的布局组件,相当重要的一个布局,这里当然要着重讲解。
Stack({
Key key,
this.alignment = AlignmentDirectional.topStart,
this.textDirection,
this.fit = StackFit.loose,
this.overflow = Overflow.clip,
List<Widget> children = const <Widget>[],
})
- alignment : 指的是子Widget的对其方式,子view从哪个方位开始对齐
- fit :用来决定没有Positioned方式时候子Widget的大小,StackFit.loose 指的是子Widget 多大就多大,StackFit.expand使子Widget的大小和父组件一样大
- overflow :指子Widget 超出Stack时候如何显示,默认值是Overflow.clip,子Widget超出Stack会被截断,Overflow.visible超出部分还会显示的
- Positioned:
这个使用控制Widget的位置,通过他可以随意摆放一个组件,有点像绝对布局
Positioned({
Key key,
this.left,
this.top,
this.right,
this.bottom,
this.width,
this.height,
@required Widget child,
})
- 配合Align使用,可以单独设置子Widget的布局方位。
Stack(
children: [
Align(
alignment: Alignment.centerLeft,
child: Text("你创作的,就是头条", style: TextStyle(fontSize: 15))
)
]