以下内容全部搬运自Flutter中文网
1
Flutter Widget采用现代响应式框架构建,中心思想是用widget构建你的UI。Widget描述了他们的视图在给定其当前配置和状态时应该看起来像什么。当widget的状态发生变化时,widget会重新构建UI,Flutter会对比前后变化的不同, 以确定底层渲染树从一个状态转换到下一个状态所需的最小更改(类似于React/Vue中虚拟DOM的diff算法)。
2
Flutter布局指南
2-1 Flutter布局方法
重点:
- Widgets 是用于构建UI的类.
- Widgets 用于布局和UI元素.
- 通过简单的widget来构建复杂的widget
Flutter布局机制的核心就是widget。在Flutter中,几乎所有东西都是一个widget ——甚至布局模型都是widget。您在Flutter应用中看到的图像、图标和文本都是widget。 甚至你看不到的东西也是widget,例如行(row)、列(column)以及用来排列、约束和对齐这些可见widget的网格(grid)。
在布局中放置一个Widget:
- 选择widget:根据想要的对齐或约束可见窗口小部件的方式,从各种布局widget中进行选择,例如Center,它可以将内容水平或垂直居中。
- 创建widget:(用来容纳对象)创建一个Icon Widget
new Icon(Icons.star, color: Colors.red[500])
- 将Widget添加到Widget中:所有布局Widget都有一个child属性(例如Center或Container),或者一个children属性,用来展示widget列表(Row,Column,ListView, Stack)。
将Icon Widget添加到
Center Widget:new Center(child: new Icon(Icons.star, color: Colors.red[500]))
- 将布局添加到页面:Flutter应用本身就是一个widget,大部分widget都有一个build()方法。在应用程序的build方法中创建会在设备上显示的widget。 对于Material应用程序,可以将Center widget直接添加到body属性中:
class _MyHomePageState extends State {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: new Text('Hello World', style: new TextStyle(fontSize: 32.0)),
),
);
}
}
Note:在设计用户界面时,可以使用标准widget库中的widget,也可以使用Material Components中的widget。 可以混合使用两个库中的widget,可以自定义现有的widget,也可以构建一组自定义的widget。
(所以目前可以考虑的widget有三种,标准库Widget,材料设计的Widget, 还有自定义Widget)
对于非Material应用程序,可以将Center widget添加到应用程序的build()方法中:
(所以Flutter的应用程序也可以分为Material应用程序和非Material应用程序)
// 这个App没有使用Material组件, 如Scaffold.
// 一般来说, app没有使用Scaffold的话,会有一个黑色的背景和一个默认为黑色的文本颜色。
// 这个app,将背景色改为了白色,并且将文本颜色改为了黑色以模仿Material app
import 'package:flutter/material.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Container(
decoration: new BoxDecoration(color: Colors.white),
child: new Center(
child: new Text('Hello World',
textDirection: TextDirection.ltr,
style: new TextStyle(fontSize: 40.0, color: Colors.black87)),
),
);
}
}
note:默认情况下,非Material应用程序不包含AppBar,标题或背景颜色。
2-2
垂直和水平放置多个Widget;
最常见的布局模式之一是垂直或水平排列widget;
使用Row水平排列widget;
使用Column垂直排列widget。
对齐Widget:控制行或列使用mainAxisAlignment和crossAxisAlignment来对齐子项。MainAxisAlignment 和CrossAxisAlignment是两个类,提供了很多属性来控制对齐效果。例如:MainAxisAlignment.spaceEvenly可以控制子项均匀分配空闲的水平空间。
2-3
如果布局太大,屏幕无法显示,在屏幕边缘会出现红色条纹。这时需要对Widget进行调整。可以将行或列的子项放置在Expandedwidget中, 以控制沿着主轴方向的widget大小。
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: new Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
new Expanded(
child: new Image.asset('images/pic1.jpg'),
),
new Expanded(
flex: 2,
child: new Image.asset('images/pic2.jpg'),
),
new Expanded(...)
2-4
聚集Widget:默认情况下,行或列沿着其主轴会尽可能占用尽可能多的空间,但如果要将孩子紧密聚集在一起,可以将mainAxisSize设置为MainAxisSize.min。 (有点类似居中的效果)
2-5
行/列嵌套(将嵌套赋值给一个变量)
class _MyHomePageState extends State {
@override
Widget build(BuildContext context) {
//...
var ratings = new Container(
padding: new EdgeInsets.all(20.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
new Row(
mainAxisSize: MainAxisSize.min,
children: [
new Icon(Icons.star, color: Colors.black),
new Icon(Icons.star, color: Colors.black),
new Icon(Icons.star, color: Colors.black),
new Icon(Icons.star, color: Colors.black),
new Icon(Icons.star, color: Colors.black),
],
),
new Text(
'170 Reviews',
style: new TextStyle(
color: Colors.black,
fontWeight: FontWeight.w800,
fontFamily: 'Roboto',
letterSpacing: 0.5,
fontSize: 20.0,
),
),
],
),
);
//...
}
}
note:为了最大限度地减少由嵌套严重的布局代码导致的视觉混淆,可以在变量和函数中实现UI的各个部分。
3
常见布局Widgets
Widget分为两类:widgets library中的标准widget和Material Components library中的专用widget。
标准 widgets:
-
Container:
- 添加 padding, margins, borders, background color, 或将其他装饰添加到widget.
- 改变背景颜色或图片;
- 包含单个子widget,但该子widget可以是Row,Column,甚至是widget树的根。
-
GridView:将 widgets 排列为可滚动的网格:
- 在网格中放置widget;
- 检测列内容超过渲染框时自动提供滚动;
- 构建您自己的自定义grid,或使用一下提供的grid之一:
- GridView.count 允许您指定列数;
- GridView.extent 允许您指定项的最大像素宽度。
-
ListView:将widget排列为可滚动列表:
- 用于组织盒子中列表的特殊Column;
- 可以水平或垂直放置;
- 检测它的内容超过显示框时提供滚动;
- 比Column配置少,但更易于使用并支持滚动
-
Stack:将widget重叠在另一个widget之上:
- 用于与另一个widget重叠的widget;
- 子列表中的第一个widget是base widget; 随后的子widget被覆盖在基础widget的顶部;
- Stack的内容不能滚动;
- 可以选择剪切超过渲染框的子项。
Material Components:
- Card:将相关内容放到带圆角和投影的盒子中:
- 实现了一个 Material Design card;
- 接受单个子项,但该子项可以是Row,Column或其他包含子级列表的widget;
- 显示圆角和阴影;
- Card内容不能滚动。
- ListTile:将最多3行文字,以及可选的行前和和行尾的图标排成一行:
- 包含最多3行文本和可选图标的专用行;
- 比起Row不易配置,但更易于使用;
- Material Components 库里的widget。