10 其他布局处理

本节介绍的组件包括矩阵转换、基准线布局、组件显示、自动换行等。

10.1 Transform(矩阵转换)

Transform的主要作用就是做矩阵变换。Container中矩阵变换就使用了Transform。Transform可以对child做平移、旋转及缩放等操作。 Transform组件的主要属性如下所示: 接下来编写一个例子,例子中使容器旋转了一定的角度。并且用的是Matrix4.rotationZ(0.3)方法进行旋转。完整的示例代码如下:

import 'package:flutter/material.dart';

class LayoutDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Transform矩阵转换示例'),
      ),
      body: new Center(
        child: Container(
          color: Colors.grey,
          child: Transform(
            alignment: Alignment.topRight,
            transform: Matrix4.rotationZ(0.3),
            child: Container(
              padding: const EdgeInsets.all(8.0),
              color: const Color(0xFFE8581C),
              child: const Text('Transform矩阵转换'),
            ),
          ),
        ),
      ),
    );
  }
}

void main() {
  runApp(
    new MaterialApp(
      title: 'Transform矩阵转换示例',
      home: new LayoutDemo(),
    ),
  );
}

上述示例代码的视图展现大致如图7-37所示。

10.2 Baseline(基准线布局)

Baseline基准线是指将所有元素底部放在同一条水平线上。做过移动端开发的读者大都了解过,一般文字排版的时候可能会用到它。它的作用很简单,根据child的baseline来调整child的位置。例如两个字号不一样的文字,希望底部在一条水平线上,就可以使用这个组件,是一个非常基础的组件。 图7-38中两个字线一上一下,如果想对齐,就需要使用到Baseline组件来控制。 Baseline组件的主要属性如下所示: 接下来编写一个小示例,示例中三个元素在同一个水平线上。baseline也设定相同的值。示例代码如下:

import 'package:flutter/material.dart';
class LayoutDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Baseline基准线布局示例'),
      ),
      body: new Row(
        //水平等间距排列子组件
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: <Widget>[
          //设置基准线
          new Baseline(
            baseline: 80.0,
            //对齐字符底部水平线
            baselineType: TextBaseline.alphabetic,
            child: new Text(
              'AaBbCc',
              style: new TextStyle(
                fontSize: 18.0,
                textBaseline: TextBaseline.alphabetic,
              ),
            ),
          ),
          new Baseline(
            baseline: 80.0,
            baselineType: TextBaseline.alphabetic,
            child: new Container(
              width: 40.0,
              height: 40.0,
              color: Colors.green,
            ),
          ),
          new Baseline(
            baseline: 80.0,
            baselineType: TextBaseline.alphabetic,
            child: new Text(
              'DdEeFf',
              style: new TextStyle(
                fontSize: 26.0,
                textBaseline: TextBaseline.alphabetic,
              ),
            ),
          ),
        ],
      ),
    );
  }
}
void main() {
  runApp(
    new MaterialApp(
      title: 'Baseline基准线布局示例',
      home: new LayoutDemo(),
    ),
  );
}   

上述示例代码的视图展现大致如图7-39所示。

10.3 Offstage(控制是否显示组件)

Offstage的作用很简单,通过一个参数来控制child是否显示,也算是比较常用的组件。Offstage组件的主要属性如下所示: 这里编写一个控制文本显示隐藏的小示例,需要添加一个控制状态的变量offstage。示例里点击右下角按钮可以显示或隐藏文本内容。完整的示例代码如下:

import 'package:flutter/material.dart';

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    final appTitle = "Offstage控制是否显示组件示例";
    return new MaterialApp(
      title: appTitle,
      home: new MyHomePage(title:appTitle),
    );
  }
}

class MyHomePage extends StatefulWidget {
  final String title;

  MyHomePage({Key key,this.title}):super(key:key);

  @override
  _MyHomePageState createState() => new _MyHomePageState();

}

class _MyHomePageState extends State<MyHomePage> {

  //状态控制是否显示文本组件
  bool offstage = true;

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: Center(
        child: new Offstage(
          offstage: offstage,//控制是否显示
          child: new Text(
            '我出来啦!',
            style: TextStyle(
              fontSize: 36.0,
            ),
          ),
        ),
      ),
      floatingActionButton: new FloatingActionButton(
        onPressed: (){

          //设置是否显示文本组件
          setState(() {
            offstage = !offstage;
          });

        },
        tooltip: "显示隐藏",
        child: new Icon(Icons.flip),
      ),

    );
  }

}   

上述示例代码的视图展现大致如图7-40所示。

10.4 Wrap(按宽高自动换行布局)

Wrap使用了Flex中的一些概念,某种意义上说跟Row、Column更加相似。单行的Wrap跟Row表现几乎一致,单列的Wrap则跟Column表现几乎一致。但Row与Column都是单行单列的,Wrap却突破了这个限制,主轴上空间不足时,则向次轴上去扩展显示。对于一些需要按宽度或高度让child自动换行布局的场景,可以使用Wrap。 Wrap组件属性见表7-3。 接下来编写一个例子,在容器里放一些头像。使用Wrap组件包装以后,头像可以按从左到右和从上到下的顺序排列头像元素。Wrap布局的完整示例代码如下:

import 'package:flutter/material.dart';

void main() {
  runApp(new MaterialApp(
    title: 'Wrap按宽高自动换行布局示例',
    home: new MyApp(),
  ));
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {

    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Wrap按宽高自动换行布局示例'),
      ),
      body: Wrap(
        spacing: 8.0, // Chip之间的间隙大小
        runSpacing: 4.0, // 行之间的间隙大小
        children: <Widget>[
          Chip(
            //添加圆形头像
            avatar: CircleAvatar(
                backgroundColor: Colors.lightGreen.shade800, child: new Text('西门', style: TextStyle(fontSize: 10.0),)),
            label: Text('西门吹雪'),
          ),
          Chip(
            avatar: CircleAvatar(
                backgroundColor: Colors.lightBlue.shade700, child: new Text('司空', style: TextStyle(fontSize: 10.0),)),
            label: Text('司空摘星'),
          ),
          Chip(
            avatar: CircleAvatar(
                backgroundColor: Colors.orange.shade800, child: new Text('婉清', style: TextStyle(fontSize: 10.0),)),
            label: Text('木婉清'),
          ),
          Chip(
            avatar: CircleAvatar(
                backgroundColor: Colors.blue.shade900, child: new Text('一郎', style: TextStyle(fontSize: 10.0),)),
            label: Text('萧十一郎'),
          ),
        ],
      ),
    );
  }
}

上述示例代码的视图展现大致如图7-41所示。