Flutter布局---Container

简介

A convenience widget that combines common painting, positioning, and sizing widgets.

Container 在Flutter中非常常见, 是一个结合绘制(painting), 定位(position)以及尺寸(sizing)的widget.

组成

Container的组成如下:

  • 最里层的是child元素;
  • child元素首先会被padding包着;
  • 然后添加额外的constraints限制;
  • 最后添加margin.

Container的绘制的过程如下:

  • 首先会绘制transform效果;
  • 接着绘制decoration;
  • 后绘制child;
  • 最后绘制foregroundDecoration.

Container自身尺寸的调节分两种情况:

  • Container在没有子节点(children)的时候,会试图去变得足够大。除非constraints是unbounded限制,在这种情况下,Container会试图去变得足够小。
  • 带子节点的Container,会根据子节点尺寸调节自身尺寸,但是Container构造器中如果包含了width、height以及constraints,则会按照构造器中的参数来进行尺寸的调节。
源码解析

构造函数如下:

Container({
    Key key,
    this.alignment,
    this.padding,
    Color color,
    Decoration decoration,
    this.foregroundDecoration,
    double width,
    double height,
    BoxConstraints constraints,
    this.margin,
    this.transform,
    this.child,
  })

属性解析

key:Container唯一标识符,用于查找更新。

alignment:控制child的对齐方式,如果container或者container父节点尺寸大于child的尺寸,这个属性设置会起作用,有很多种对齐方式。

padding:decoration内部的空白区域,如果有child的话,child位于padding内部。padding与margin的不同之处在于,padding是包含在content内,而margin则是外部边界,设置点击事件的话,padding区域会响应,而margin区域不会响应。

color:用来设置container背景色,如果foregroundDecoration设置的话,可能会遮盖color效果。

decoration:绘制在child后面的装饰,设置了decoration的话,就不能设置color属性,否则会报错,此时应该在decoration中进行颜色的设置。

foregroundDecoration:绘制在child前面的装饰。

width:container的宽度,设置为double.infinity可以强制在宽度上撑满,不设置,则根据child和父节点两者一起布局。

height:container的高度,设置为double.infinity可以强制在高度上撑满。

constraints:添加到child上额外的约束条件。

margin:围绕在decoration和child之外的空白区域,不属于内容区域。

transform:设置container的变换矩阵,类型为Matrix4。

child:container中的内容widget。

源码
decoration = decoration ?? (color != null ? new BoxDecoration(color: color) : null),

可以看出, 对于颜色的设置,最后都是转换为decoration来进行绘制的。如果同时包含decoration和color两种属性,则会报错。

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

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

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

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

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

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

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

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

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

    return current;
  }

Container 的 build 函数的绘制过程是一个线形的判断过程, 一层层的包裹着Widget, 去实现不同的样式.

示例
void main() => runApp(MyApp());


class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);
  @override
  _MyHomePage createState() => _MyHomePage();
}

class _MyHomePage extends State {

  String textToShow = "I like Flutter";

  void _updateText(){
    print('点击');
    setState(() {
      textToShow = "Flutter is Awesome";
    });
    Navigator.push(
      context,
      new MaterialPageRoute(builder: (context) => new SamplePage())
    );
  }
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
          title: Text("Sample App")
      ),
      body: new Container(
        constraints: new BoxConstraints.expand(
          height: Theme.of(context).textTheme.display1.fontSize * 1.1 + 200
        ),
        decoration: new BoxDecoration(
          border: new Border.all(width: 2.0, color: Colors.red),
          color: Colors.grey,
          borderRadius: new BorderRadius.all(new Radius.circular(20)),
          image: new DecorationImage(
              image: new NetworkImage('http://h.hiphotos.baidu.com/zhidao/wh%3D450%2C600/sign=0d023672312ac65c67506e77cec29e27/9f2f070828381f30dea167bbad014c086e06f06c.jpg'),
              centerSlice: new Rect.fromLTRB(270, 180, 1360, 730)
          ),
        ),
        padding: const EdgeInsets.all(8.0),
        alignment: Alignment.center,
        child: new Text(textToShow,
          style: Theme.of(context).textTheme.display1.copyWith(color: Colors.black),
        ),
        transform: new Matrix4.rotationZ(0.3),
      ),
      floatingActionButton: FloatingActionButton(
          onPressed: _updateText,
          tooltip: 'Update Text',
          child: Icon(Icons.update),
      ),
    );
  }
}
Flutter布局---Container_第1张图片
屏幕快照 2019-07-29 下午2.57.48.png
使用场景
  • 需要设置间隔
  • 需要设置背景
  • 需要设置圆角或者边框
  • 需要对齐
  • 需要设置背景图片

你可能感兴趣的:(Flutter布局---Container)