容器组件(Container)包含了一个子Widget,自身具备如alignment、padding等基础属性,方便布局过程中摆放child。
Container组件属性及描述
属性名 | 类型 | 说明 |
---|---|---|
Key | Key | Container唯一标识符,用于查找更新 |
alignment | AlignmentGeometry | 控制child的对齐方式, 如果Container或者Container父节点 尺寸大于child的尺寸,这个属性设置 会起作用,且有很多种对齐方式 |
padding | EdgeInsetsGeometry | Decoration内部的空白区域,如果有child的话, child位于padding内部 |
color | Color | 用来设置Container背景色, 如果foregroundDecoration设置的话,可能会 遮盖color效果 |
decoration | Decoration | 绘制在child后面的装饰,设置了Decoration的 话就不能设置Color属性,否则会报错,此时应该 在Decoration中进行颜色的设置 |
foregroundDecoration | Decoration | 绘制在child前面的装饰 |
width | double | Container的宽度,设置会double.infinity可以强制 在宽度上撑满,不设置则根据child和父节点两者一起布局 |
height | double | Container的宽度,设置会double.infinity可以强制 在高度上撑满 |
constraints | BoxContraints | 添加到child的额外的约束条件 |
margin | EdgeInsetsGeometry | 围绕在Decoration和child之外的空白区域,不属于内容区域 |
transform | Matrix4 | 设置Container的变换矩阵,类型是Matrix4 |
child | Widget | Container中的Widget |
提示:
--Container在Flutter中太常见了。官方给出的简介,是一个结合了绘制(painting)、定位(positioning)以及尺寸(sizing)widget的widget
--padding和margin的不同之处在于,padding是包含在Container内,而margin是外部边界。设置点击事件的话,padding区域会响应,而margin区域不会响应。
--decoration是container的装饰器 可以设置边框,边框圆角,阴影,背景图,渐变色,形状,背景色等等
组成和绘制
Container的组成如下
最里层是child元素;
child元素首先会被padding包着;
然后添加额外的constraints限制;
最后添加margin
Container的绘制流程如下
首先会绘制transform效果;
接着绘制decoration;
然后绘制child;
最后绘制foregroundDecoration
Container自身的尺寸调节分两种情况
Container在没有子节点(children)的时候,会试图去变得足够大。除非constraints是unbounded限制,在这种情况下,Container会试图去变得足够小。
带子节点的Container,会根据子节点尺寸调节自身尺寸,但是Container构造器中如果包含了width、height以及constraints,则会按照构造器中的参数来进行尺寸的调节
Container布局行为
由于Container组合了一系列的widget,这些widget都有自己的布局行为,因此Container的布局行为有时候是比较复杂的。
一般情况下,Container会遵循如下顺序去尝试布局
对齐(alignment);
调节自身尺寸适合子节点;
采用width、height以及constraints布局;
扩展自身去适应父节点;
调节自身到足够小
进一步解释
如果没有子节点、没有设置width、height以及constraints,并且父节点没有设置unbounded的限制,Container会将自身调整到足够小。
如果没有子节点、对齐方式(alignment),但是提供了width、height或者constraints,那么Container会根据自身以及父节点的限制,将自身调节到足够小。
如果没有子节点、width、height、constraints以及alignment,但是父节点提供了bounded限制,那么Container会按照父节点的限制,将自身调整到足够大。
如果有alignment,父节点提供了unbounded限制,那么Container将会调节自身尺寸来包住child;
如果有alignment,并且父节点提供了bounded限制,那么Container会将自身调整的足够大(在父节点的范围内),然后将child根据alignment调整位置;
含有child,但是没有width、height、constraints以及alignment,Container会将父节点的constraints传递给child,并且根据child调整自身
代码示例
- 展示一个Container, 长100,宽100,marginTop100,marginLeft100
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "容器组件-Container",
home: Scaffold(
appBar: AppBar(
title: Text("容器组件-Container"),
centerTitle: true,
),
body: Container(
margin: EdgeInsets.only(left: 100.0, top: 100.0),
width: 100.0,
height: 100.0,
color: Color(0xFFFF00FF),
),
),
);
}
}
- Container内部嵌套Container,居中显示
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "容器组件-Container",
home: Scaffold(
appBar: AppBar(
title: Text("容器组件-Container"),
centerTitle: true,
),
body: Container(
alignment: Alignment.center,
margin: EdgeInsets.only(left: 100.0, top: 100.0),
padding: EdgeInsets.all(10.0),
width: 100.0,
height: 200.0,
color: Color(0xFFFF00FF),
child: new Container(
color: Colors.yellow,
child: new Text("容器组件", style: new TextStyle(fontSize: 20.0)),
),
),
),
);
}
}
- decoration设置背景色,注意decoration和color不能共存(共存引起异常如下),只能设置一个,decoration不仅能设置颜色还能设置渐变色
I/flutter (26809): When the exception was thrown, this was the stack:
I/flutter (26809): #2 new Container (package:flutter/src/widgets/container.dart:269:15)
I/flutter (26809): #3 _MyAppState.build (package:flutter_widget_peoject/main.dart:20:15)
I/flutter (26809): #4 StatefulElement.build (package:flutter/src/widgets/framework.dart:3809:27)
I/flutter (26809): #5 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3721:15)
I/flutter (26809): #6 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
I/flutter (26809): #7 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2286:33)
I/flutter (26809): #8 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:691:20)
I/flutter (26809): #9 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:219:5)
I/flutter (26809): #10 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:990:15)
I/flutter (26809): #11 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:930:9)
I/flutter (26809): #12 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.scheduleWarmUpFrame. (package:flutter/src/scheduler/binding.dart:751:7)
I/flutter (26809): #14 _Timer._runTimers (dart:isolate/runtime/libtimer_impl.dart:382:19)
I/flutter (26809): #15 _Timer._handleMessage (dart:isolate/runtime/libtimer_impl.dart:416:5)
I/flutter (26809): #16 _RawReceivePortImpl._handleMessage (dart:isolate/runtime/libisolate_patch.dart:171:12)
I/flutter (26809): (elided 3 frames from class _AssertionError and package dart:async)
下面设置Container背景色为线性渐变(LinearGradient,其他还可以设置RadialGradient和SweepGradient渐变)
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "容器组件-Container",
home: Scaffold(
appBar: AppBar(
title: Text("容器组件-Container"),
centerTitle: true,
),
body: Container(
margin: EdgeInsets.only(left: 100.0, top: 100.0),
width: 100.0,
height: 100.0,
// color: Color(0xFFFF00FF),
decoration: new BoxDecoration(
gradient: const LinearGradient(colors: [
Colors.lightBlue,
Colors.greenAccent,
Colors.purple
])),
),
),
);
}
}
- Container前景色foregroundDecoration设置
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "容器组件-Container",
home: Scaffold(
appBar: AppBar(
title: Text("容器组件-Container"),
centerTitle: true,
),
body: Container(
margin: EdgeInsets.only(left: 100.0, top: 100.0),
width: 100.0,
height: 100.0,
// color: Color(0xFFFF00FF),
decoration: new BoxDecoration(
gradient: const LinearGradient(colors: [
Colors.lightBlue,
Colors.greenAccent,
Colors.purple
])),
foregroundDecoration: new BoxDecoration(
border: new Border.all(
color: Colors.redAccent, width: 10.0, style: BorderStyle.solid),
shape: BoxShape.circle,
),
),
),
);
}
}