Flutter 所有元素都是由组件组成,因此其核心理念是一切皆为组件。
Container
(容器组件)一个简便的组件,其结合了常见的绘制、定位和调整尺寸的组件。这一点我们可以通过其构造函数看出。
Container({
Key key, //Container唯一标识符,用于查找更新
AlignmentGeometry alignment, //控制child对齐方式
EdgeInsetsGeometry padding, //内部空白区域
Color color, //背景色
Decoration decoration, //绘制child后面的装饰,若设置该属性,则不能设置color属性
Decoration foregroundDecoration, //绘制child前面的装饰
double width, //Container宽度
double height, //Container高度
BoxConstraints constraints, //添加到child上的额外约束条件
EdgeInsetsGeometry margin, //外部空白区域
Matrix4 transform, //变换矩阵
Widget child //内容组件
})
容器通过参数中的内边距包围子元素,然后对根据额外的约束条件来填充范围(如果宽度和高度都是非空的,则将宽度和高度合并为约束)。然后整个容器被外边距包围。内边距属性(
padding
)和外边距属性(margin
)不同之处在于,内边距属性是包含内容区域,而外边距属性是在内容区域之外,不包含内容区域。因此,若存在点击事件时,内边距区域会响应,而外边距区域不会响应。
容器绘制过程:
- 首先绘制变换矩阵(
transform
);
transform: Matrix4.rotationZ(0.1),
- 接着绘制child后面的装饰(
decoration
),并填充范围;
//由于color最终是以decoration方式来绘制的,因此两种只能存其一。
//color: Colors.teal.shade700,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage("https://cdn.jsdelivr.net/gh/flutterchina/website@1.0/images/flutter-mark-square-100.png")
)
),
- 然后绘制内容组件(
child
);
child: Text(
"Hello Container!",
style: Theme.of(context).textTheme.display1.copyWith(
color: Colors.red
),
),
- 最后绘制child前面的装饰(
foregroundDecoration
)。
foregroundDecoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage("https://cdn.jsdelivr.net/gh/flutterchina/website@1.0/images/flutter-mark-square-100.png"),
centerSlice: Rect.fromLTRB(270.0, 280.0, 1360.0, 730.0)
)
),
容器尺寸范围:
- 没有子元素的容器尝试尽可能大,除非传入的约束是无界的,这种情况下,它们尝试尽可能小。
- 存在子元素的容器根据子元素来调整尺寸。
- 通过构造函数的宽(
width
)、高(height
)和额外约束条件(constraints
)来限制。
width: 148.0,
height: 148.0,
constraints: BoxConstraints.expand(
height: Theme.of(context).textTheme.display1.fontSize * 1.1 + 200.0
),
布局行为:
- 关于合布局模型的介绍,参见
BoxConstraint
。 - 由于容器结合了许多拥有自己布局行为的其他组件,所以容器的布局行为有点复杂。
- 容器会按照以下顺序尝试布局:对齐原则,按照子元素的大小调整自身,遵循宽、高和约束条件,按照父元素的大小进行扩展,尽可能小。
- 具体来说:
- 如果没有子组件、没有高度、没有宽度、没有约束条件的限制,而且父组件提供了无界约束,那么容器将尝试调整自身大小尽可能小。
- 如果没有子组件、没有对齐,但提供了高度、宽度或约束条件,那么容器将在这些约束条件和父元素约束的组合下尽可能小。
- 如果没有子组件、没有高度、没有宽度、没有约束条件和对齐方式的限制,但父组件提供了有界约束,那么容器将扩充以适应父组件提供的约束。
- 如果组件具有对齐方式,并且父组件提供无界约束,那么容器将尝试围绕子组件调整自身大小。
- 如果组件具有对齐方式,并且父组件提供有界约束,那么容器将尝试以适应父组件,然后根据对齐方式将子组件放置在自己内部。
- 另外,组件含有一个小组件,但没有高度、宽度、约束和对齐方式,容器会将约束从父组件传递给子组件,并将大小本身与子组件匹配。
- 外边距和内边距也会影响布局,如这些属性的文档中所述,参考
Decoration.padding
。
//此实例展示了一个在中间的48*48的小绿块,并对其设置了外边距,以便与其他组件保持距离。
Center(
child: Container(
margin: const EdgeInsets.all(10.0),
color: const Color(0xFF00FF00),
width: 48.0,
height: 48.0,
),
)
下面是一个完整的实例,其展示了Flutter官方的Logo图标,并设置前装饰和后装饰以及文字内容,我们可以看出后装饰再最顶层,而前装饰在最底层。
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Container',
home: Scaffold(
body: Center(
child: Container(
alignment: Alignment.center,
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(10.0),
//color: Colors.teal.shade700,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage("https://cdn.jsdelivr.net/gh/flutterchina/website@1.0/images/flutter-mark-square-100.png")
)
),
foregroundDecoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage("https://cdn.jsdelivr.net/gh/flutterchina/website@1.0/images/flutter-mark-square-100.png"),
centerSlice: Rect.fromLTRB(270.0, 280.0, 1360.0, 730.0)
)
),
width: 148.0,
height: 148.0,
constraints: BoxConstraints.expand(
height: Theme.of(context).textTheme.display1.fontSize * 1.1 + 200.0
),
transform: Matrix4.rotationZ(0.1),
child: Text(
"Hello Container!",
style: Theme.of(context).textTheme.display1.copyWith(
color: Colors.red
),
),
),
),
),
);
}
}
Container的继承关系:
Object > Diagnosticable > DiagnosticableTree > Widget > StatelessWidget > Container
属性:
属性名 | 类型 | 说明 |
---|---|---|
key | Key | Container唯一标识符 |
alignment | AlignmentGeometry | 控制子元素对齐方式 |
child | Widget | 内容组件 |
constraints | BoxConstraints | 添加到子元素上额外的约束条件 |
decoration | Decoration | 绘制子元素后的装饰 |
foregroundDecoration | Decoration | 绘制子元素前的装饰 |
margin | EdgeInsetsGeometry | 外边距 |
padding | EdgeInsetsGeometry | 内边距 |
transform | Matrix4 | 变换矩阵 |
hashCode | int | 哈希码 |
runtimeType | Type | 对象运行时类型的表示形式 |
方法:
方法名 | 类型 | 说明 |
---|---|---|
build(BuildContext context) | Widget | 组件表示的部分用户界面 |
debugFillProperties(DiagnosticPropertiesBulider properties) | void | 添加与节点关联的其他属性 |
createElement | StatelessElement | 创建一个StatelessElement 来管理组件在树中的位置 |
debugDescribeChildren() | List<DiagnosticsNode> | 返回描述词节点子节点的diagnostics 节点对象列表 |
noSuchMethod(Invocation invocation) | dynamic | 当访问不存在的方法或属性时调用 |
toDiagnosticsNode({String name, DiagnosticsTreeStyle style}) | DiagnosticsNode | 返回由使用调试工具和DiagnostisNode.toStringDep的对象的调试表示形式 |
toString({DiagnosticLevel minLevel: DiagnosticLevel.debug}) | String | 返回此对象的字符串表示形式 |
toStringDeep({String prefixLineOne:'', String prefixOtherLines, DiagnosticLevel minLevel: DiagnosticLevel.debug}) | String | 返回子节点和它的子节点的字符串表示形式 |
toStringShallow({Sting joiner:',', DiagnosticLevel minLevel:DiagnosticLevel.debug}) | String | 返回对象的一行详细说明 |
toStringShort() | String | 对组件简短的文本描述 |
参考文档:Container class