• Step 6:集成上述组件
    #####Flutter布局方法
    #####布局一个组件
    #####横向及竖向布局多个组件
    • 组件对齐方式
    • 调整组件大小
    • 缩紧组件
    • 嵌套行与列
      #####常用布局组件
    • 标准组件
    • Material组件
      #####资源
      #搭建布局

      若你想理解“big picture”的布局原理,那么需要学习Flutter布局方法。

##Step 0:创建
#####首页获取代码:

  • 确定已经设置好环境
  • 创建基本Flutter工程

#####下来在工程中添加图片:

  • 在工程根目录创建images目录
  • 添加 lake.jpg 图片
  • 更新 pubspec.yaml 文件,添加 assets 标签

##Step 1:图解布局
#####第一步是将布局分解成基本元素:

  • 区分行与列。
  • 布局是否包含一个网格?
  • 是否有层叠元素?
  • UI是否需要tabs?
  • 注意需要对齐,内边据或者边框的区域。

    首先,识别更大的元素。在这里,四个元素在同一列中:一个图片,两行和一个文本块。

Flutter这么火为什么不了解一下呢?,阿里专家原创

接下来,图解每行。第一行,我们称其Title Section,有3个子组件:一列文本区域,一个星型图标,及一个数字。第一列子组件包含2行文本。且第一列占有较大空间,因此需要将两行文本放在Expanded组件中。

Flutter这么火为什么不了解一下呢?,阿里专家原创

第二行,我们称其Button section,同样有3个子组件:由三列组成,且每列均由一个图标和文本组成。

Flutter这么火为什么不了解一下呢?,阿里专家原创

在图解了布局之后,再从细节到整体来实现这个布局就容易了。为了让嵌套的代码看起来不那么混乱,我们将一些实现置于变量和函数中。

Step 2:实现Title Section

首先需要在Title Section左侧创建一列。在Expanded组件中的Column组件使得当前列(column并非组件)可以覆盖真个Title section. 将Column组件的 crossAxisAlignment 属性设置CrossAxisAlignment.start ,这样Column组件位于当前行的起始位置。

将第一行的文本组件放置于Container组件中以便添加Container内边据。第二个文本组件文字是灰色。

最后的2个组件包括一个红色星型图标和一个数字“41”的文本。将整个标题行(Title Section图解中的Row with 3 children)放置在一个Container组件中,并且设置Container组件32px的内边距。

Note: 如何代码实现有问题,可以依据Github上的lib/main.dart 来检查你的代码。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    Widget titleSection = new Container(
      padding: const EdgeInsets.all(32.0),
      child: new Row(
        children: [
          new Expanded(
            child: new Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                new Container(
                  padding: const EdgeInsets.only(bottom: 8.0),
                  child: new Text(
                    'Oeschinen Lake Campground',
                    style: new TextStyle(
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                ),
                new Text(
                  'Kandersteg, Switzerland',
                  style: new TextStyle(
                    color: Colors.grey[500],
                  ),
                ),
              ],
            ),
          ),
          new Icon(
            Icons.star,
            color: Colors.red[500],
          ),
          new Text('41'),
        ],
      ),
    );
  //...
}

Tip: 粘贴代码到工程中时,代码缩进可能错乱。如果是在IntelliJ中,可以有单机选择Reformat with Dart Style。或者在命令行中使用dartfmt命令。

Tip: 为体验更快开发过程,尝试使用Flutter的热加载功能。热加载使得在修改代码同时快速地在查看到修改后的效果,而不用重运行app。

##Step 3:实现按钮行(Button Section)

Button Section包含3列相同的布局——一个图标和一个文本。这行中3列均匀分布,并且文本和图标颜色是APP build()方法中设置的primary color。


class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// title section implementation
return new MaterialApp(
  title: 'Flutter Demo',
  theme: new ThemeData(
    primarySwatch: Colors.blue,
  ),

//...

}

> 由于创建每列的代码是相同的,最高效的办法就是创建一个嵌套函数,例如就定义为buildButtonColumn(),这个方法中创建包含一个图标和一个文本得组件,并且返回Column对象。

class MyApp extends StatelessWidget {br/>@override
Widget build(BuildContext context) {
//…

Column buildButtonColumn(IconData icon, String label) {
  Color color = Theme.of(context).primaryColor;

  return new Column(
    mainAxisSize: MainAxisSize.min,
    mainAxisAlignment: MainAxisAlignment.center,
    children: [
      new Icon(icon, color: color),
      new Container(
        margin: const EdgeInsets.only(top: 8.0),
        child: new Text(
          label,
          style: new TextStyle(
            fontSize: 12.0,
            fontWeight: FontWeight.w400,
            color: color,
          ),
        ),
      ),
    ],
  );
}

//…
}

>这个创建方法中直接添加icon组件。将文本组件放于Container组件中来添加上边距,将icon与text分离开。

class MyApp extends StatelessWidget {br/>@override
Widget build(BuildContext context) {
//…

Widget buttonSection = new Container(
  child: new Row(
    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
    children: [
      buildButtonColumn(Icons.call, 'CALL'),
      buildButtonColumn(Icons.near_me, 'ROUTE'),
      buildButtonColumn(Icons.share, 'SHARE'),
    ],
  ),