简介
对于我们已经特别熟悉了前端的同学来说,HTML + CSS 来布局已经是可以各种花式操作了,但是对于 Flutter 这个框架来说,感觉就不一样了,因为 Flutter 上面已经不在使用 CSS 的那套语法了。所以就需要重新来看 Flutter 的布局。
先引用官方的一段话。点击这里跳转到官网。
重点是什么?
- Widgets 是用于构建UI的类.
- Widgets 用于布局和UI元素.
- 通过简单的widget来构建复杂的widget
Flutter 布局的机制的核心就是在 widget。在 Flutter 中,几乎所有的东西都是一个 widget-甚至布局模型都是 widget。您在Flutter应用中看到的图像、图标和文本都是widget。 甚至你看不到的东西也是widget,例如行(row)、列(column)以及用来排列、约束和对齐这些可见widget的网格(grid)。
图片中显示的布局结构,一个行包含3列,其中每列包含一个图标和一个标签。
以下是此UI的widget树示意图,我们可以清晰的看到 widget 的包含关系。
布局组件
所有的布局 widget 都有一个 child
属性(例如:Center 或 Container), 或者一个children
属性,如果他们需要一个 widget 列表(例如 Row, Column, ListView 或者 Stack)
容纳可见对象的 widget
Image widget
Image 的多种构造方法
- new Image, 通用方法,使用ImageProvider实现,如下方法本质上也是使用的这个方法
- new Image.asset,用于使用key从AssetBundle获取图像。
- new Image.network,用于从URL地址获取图像。
- new Image.file,用于从File获取图像。
为了自动执行像素密度感知资源分辨率,使用AssetImage指定图像,需要确保在控件树中的图片控件上方存在MaterialApp、WidgetsApp和MediaQuery控件。
// 获取资源图片
new Image.asset('images/myPic.jpg')
// 从网络上面获取图片
new Image.network(
'https://flutter.io/images/homepage/screenshot-2.png',
scale: 2.0)
// 使用ImageProvider 加载图片
new Image(image: new NetWorkImage("https://flutter.io/images/homepage/screenshot-2.png"))
图片的 width 和 heigth
new Image.asset( 'imgs/logo.jpeg', width: 200.0, height: 100.0, fit: BoxFit.fill );
在使用本地图片之前,我们需要指定本地图片的路径。在 pubspec.yaml
文件中配置
# To add assets to your application, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
Text widget
// 新建一个展示文字的控件,通过 style: new TextStyle() 来给文字增加样式
new Text('Hello World', style: new TextStyle(fontSize: 32.0))
创建一个 Icon widget:
图标控件,图标控件是没有交互功能的,只能作为展示使用,如果需要有交互功能,可以使用 Material 中的 IconButton。
详细可以查看官方文档:https://docs.flutter.io/flutter/widgets/Icon-class.html
new Icon(Icons.star, color: Colors.red[500])
Container 组件
容器,一个常用的控件,由基本的绘制、位置和大小控件组成。负责创建矩形的可视元素,可以用BoxDecoration来设计样式,比如背景、边框和阴影,Container也有边距、填充和大小限制,另外,还可以在三维空间利用矩阵进行变换。
Container 概要:
- 添加 padding,margins,borders
- 改变背景颜色或者图片
- 包含单个子 widget,但是该子 widget 可以是 Row, Column, 甚至是 widget 树的根
- 属性decoration和color无法共存
- Container默认是尽可能大的占用空间, 但是如果你给它指定一个width,那它就会采用指定的值
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter demo',
home: new Container(
decoration: new BoxDecoration(
color: Colors.white
),
child: new Center(
child: new Text('Hello World',
style: new TextStyle(fontSize: 20.0, color: Colors.black87)),
),
)
);
}
}
图示
Row 和 Column
最常见的布局模式之一是垂直或水平排列widget。我们可以使用行(Row)水平排列widget,并使用列(Column)垂直排列widget。
简要说明
- 行和列是两种最常用的布局模式
- 行和列都需要一个子widget列表
- 子widget本身可以是行、列或其他复杂widget
- 可以指定行或列如何在垂直或水平方向上对齐其子项
- 可以拉伸或限制特定的子widget
- 可以指定子widget如何使用行或列的可用空间
Row
flex水平布局控件,能够将子控件水平排列,是基于Web的flexbox的布局模式设计的。
Row子控件有灵活与不灵活的两种,Row首先列出不灵活的子控件,减去它们的总宽度,计算还有多少可用的空间。然后Row按照Flexible.flex属性确定的比例在可用空间中列出灵活的子控件。要控制灵活子控件,需要使用Expanded控件。
如果只有一个子控件,可以使用 Align or Center控件定义该子控件位置。
new Row(
children: <Widget>[
new Expanded(
child: new Text('Deliver features faster', textAlign: TextAlign.center),
),
new Expanded(
child: new Text('Craft beautiful UIs', textAlign: TextAlign.center),
),
new Expanded(
child: new FittedBox(
fit: BoxFit.contain, // otherwise the logo will be tiny
child: const FlutterLogo(),
),
),
],
)
Column
flex垂直布局控件,能够将子控件垂直排列。
new Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new Text('We move under cover and we move as one'),
new Text('Through the night, we have one shot to live another day'),
new Text('We cannot let a stray gunshot give us away'),
new Text('We will fight up close, seize the moment and stay in it'),
new Text('It’s either that or meet the business end of a bayonet'),
new Text('The code word is ‘Rochambeau,’ dig me?'),
new Text('Rochambeau!', style: DefaultTextStyle.of(context).style.apply(fontSizeFactor: 2.0)),
],
)
注
比较复杂的布局,可以看下官网:https://flutterchina.club/tutorials/layout/