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

    原文作者:ohayoi
    原文地址: https://www.jianshu.com/p/a70f866c0604
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞