记录自学flutter点点滴滴

Flutter 学习之旅(九) 基础控件 Containe

2020-08-13  本文已影响0人  Tsm_2020

Container

这是一个组合控件, 看了一下他的源码可以用非常简单来描述,但是他在这种布局的表现就非常的复杂,先来看一下为什么说他非常简单

看一下他的build方法

 @override
  Widget build(BuildContext context) {
    Widget current = child;

    if (child == null && (constraints == null || !constraints.isTight)) {
      current = LimitedBox(
        maxWidth: 0.0,
        maxHeight: 0.0,
        child: ConstrainedBox(constraints: const BoxConstraints.expand()),
      );
    }

    if (alignment != null)
      current = Align(alignment: alignment, child: current);

    final EdgeInsetsGeometry effectivePadding = _paddingIncludingDecoration;
    if (effectivePadding != null)
      current = Padding(padding: effectivePadding, child: current);

    if (color != null)
      current = ColoredBox(color: color, child: current);

    if (decoration != null)
      current = DecoratedBox(decoration: decoration, child: current);

    if (foregroundDecoration != null) {
      current = DecoratedBox(
        decoration: foregroundDecoration,
        position: DecorationPosition.foreground,
        child: current,
      );
    }

    if (constraints != null)
      current = ConstrainedBox(constraints: constraints, child: current);

    if (margin != null)
      current = Padding(padding: margin, child: current);

    if (transform != null)
      current = Transform(transform: transform, child: current);

    if (clipBehavior != Clip.none) {
      current = ClipPath(
        clipper: _DecorationClipper(
          textDirection: Directionality.of(context),
          decoration: decoration
        ),
        clipBehavior: clipBehavior,
        child: current,
      );
    }

    return current;
  }

完全就是一层嵌套一层,做过前端的可能很多属性都知道怎么回事,但是这里面有几个属性还是有必要提及一下的,

constraints

constraints 这个是用来约束子布局的,如果Container 的子布局是一个Text (),但是Text()这个控件没有width 和height这两个属性,

就可以通过constraints 这个属性在父布局中设置

一般设置方法

constraints:BoxConstraints.expand(width:200, height:200)

alignment

在控件在Container中的对齐方式,经常用的有Alignment.center Alignment.left 等等

这里面有一个比较有意思的地方,就是Alignment这个类描述各个点在这个二位空间的位置,值(-1~1表示距离权重)

中心点为0,0,那么topleft 应该是(-1,-1) 而topright(1,-1),这个就是他的构造方法,自己好好想一下,其实还是很有意思的

  /// The top left corner.
  static const Alignment topLeft = Alignment(-1.0, -1.0);

  /// The center point along the top edge.
  static const Alignment topCenter = Alignment(0.0, -1.0);

  /// The top right corner.
  static const Alignment topRight = Alignment(1.0, -1.0);

  /// The center point along the left edge.
  static const Alignment centerLeft = Alignment(-1.0, 0.0);

  /// The center point, both horizontally and vertically.
  static const Alignment center = Alignment(0.0, 0.0);

  /// The center point along the right edge.
  static const Alignment centerRight = Alignment(1.0, 0.0);

  /// The bottom left corner.
  static const Alignment bottomLeft = Alignment(-1.0, 1.0);

  /// The center point along the bottom edge.
  static const Alignment bottomCenter = Alignment(0.0, 1.0);

  /// The bottom right corner.
  static const Alignment bottomRight = Alignment(1.0, 1.0);

decoration
这个其实就是android中drawable 配置文件设置背景的的方式,参数名都没怎么变,直接上例子,


    decoration: BoxDecoration(
            color: Colors.redAccent,/// 背景色  如果这里设置了color 外部就不能设置,否则报错
            borderRadius: BorderRadius.all(Radius.circular(6)),/// 圆角
            border: Border.all(color: Colors.black87, width: 2),///边框线 的颜色与宽度
            gradient: LinearGradient(///渐变色  这里使用的是线性渐变
              begin: Alignment.topLeft,
              end: Alignment(0.5, 0.5),
              // 10% of the width, so there are ten blinds.
              colors: [Colors.redAccent, Colors.purpleAccent],
              // whitish to gray
              tileMode:
                  TileMode.repeated, // repeats the gradient over the canvas
            ),
            boxShadow: <BoxShadow>[///阴影颜色
              BoxShadow(
                color: Colors.green,
                offset: Offset(2, 2),
              )
            ]),

decoration 中还能直接设置背景图片,使用image属性,我这里才用的线性渐变,就不用了,

这里面比较有意思的属性是 transform 这个属性,

看到了我给的是值是Matrix4.rotationZ(cos(60)) ,

image

这种旋转是围绕着z轴做选中,实际你看到的偏移量是x轴和y轴的距离做了偏移,看一下实际效果,

image

我命名给的是Z轴旋转,为什么是x轴与y轴的的值发生了变化,看了上面那个旋转坐标系后才恍然大悟

最后再来说一下他为什么复杂,那是因为他的大小收子控件与对齐方式,还有父控件的大小等等很多因素干扰,

在源码的注释上面是这样提及的

 If the widget has no child, no `height`, no `width`, no [constraints],
 and the parent provides unbounded constraints, then [Container] tries to
 size as small as possible.

 If the widget has no child and no [alignment], but a `height`, `width`, or
 [constraints] are provided, then the [Container] tries to be as small as
 possible given the combination of those constraints and the parent's
 constraints.

 If the widget has no child, no `height`, no `width`, no [constraints], and
 no [alignment], but the parent provides bounded constraints, then
 [Container] expands to fit the constraints provided by the parent.

 If the widget has an [alignment], and the parent provides unbounded
 constraints, then the [Container] tries to size itself around the child.

 If the widget has an [alignment], and the parent provides bounded
 constraints, then the [Container] tries to expand to fit the parent, and
 then positions the child within itself as per the [alignment].

 Otherwise, the widget has a [child] but no `height`, no `width`, no
 [constraints], and no [alignment], and the [Container] passes the
 constraints from the parent to the child and sizes itself to match the
 child.

这段话的意思大概就是

如果没有子布局、没有设置width、height以及constraints,并且父布局没有设置unbounded的限制,Container会将自身调整到足够小 (warp_centent)。

如果没有子布局、alignment,但是提供了width、height或者constraints,那么Container会根据自身以及父布局的限制,将自身调节到足够小。例如margin padding (warp_centent)

如果没有子布局、width、height、constraints以及alignment,但是父布局提供了bounded限制,那么Container会按照父布局的限制,将自身调整到足够大,直至填充满父布局的约束 (match_parent)。

如果有alignment,父布局提供了unbounded限制,那么Container将会调节自身尺寸来包住child 类似(warp_centent);

如果有alignment,并且父布局提供了bounded限制,那么Container会将自身调整的足够大(在父节点的范围内),然后将child根据alignment调整位置 (match_parent);

含有child,但是没有width、height、constraints以及alignment,Container会将父节点的constraints传递给child,并且根据child调整自身 (warp_centent)。

最后总结一下:

如果父布局添加了布局边界bounded的限制,则将会填充满父控件,否则将将按照内部子布局的约束来,

感觉这里还是有很多地方不是很理解,只能在接下来的使用过程中慢慢总结吧,

我学习flutter的整个过程都记录在里面了
https://www.jianshu.com/c/36554cb4c804

最后附上demo 地址

https://github.com/tsm19911014/tsm_flutter

上一篇 下一篇

猜你喜欢

热点阅读