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

属性:

属性名类型说明
keyKeyContainer唯一标识符
alignmentAlignmentGeometry控制子元素对齐方式
childWidget内容组件
constraintsBoxConstraints添加到子元素上额外的约束条件
decorationDecoration绘制子元素后的装饰
foregroundDecorationDecoration绘制子元素前的装饰
marginEdgeInsetsGeometry外边距
paddingEdgeInsetsGeometry内边距
transformMatrix4变换矩阵
hashCodeint哈希码
runtimeTypeType对象运行时类型的表示形式

方法:

方法名类型说明
build(BuildContext context)Widget组件表示的部分用户界面
debugFillProperties(DiagnosticPropertiesBulider properties)void添加与节点关联的其他属性
createElementStatelessElement创建一个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
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞