Flutter初学之路—`Container` (容器组件)

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,843评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,538评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,187评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,264评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,289评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,231评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,116评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,945评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,367评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,581评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,754评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,458评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,068评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,692评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,842评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,797评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,654评论 2 354

推荐阅读更多精彩内容

  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 13,751评论 1 92
  • Flutter中的布局容器主要分为两类:只能包含一个子Widget的布局容器和可以包含多个子Widget的容器,下...
    彡廿阅读 2,454评论 0 19
  • •1.1语法 •ES6语法:ECMAScript6.0(以下简称ES6)是JavaScript语言的下一代标准,已...
    ScottStone阅读 583评论 1 2
  • 简介 Container class一个便利的控件,结合了常见的绘画,定位和大小调整。 容器(Container ...
    鱼Fcn阅读 884评论 0 0
  • CSS 是什么 css(Cascading Style Sheets),层叠样式表,选择器{属性:值;属性:值}h...
    崔敏嫣阅读 1,482评论 0 5