Flutter :布局 Widget

684 阅读3分钟

本期周记里主要记录使用 Flutter 开发中布局 Widget 相关的知识。

1.Flutter 中有哪些布局 Widget

所谓布局 widget 即对齐或限制可见 widget 的方式,类似于 Android 原生开发中的 LinearLayout(线性布局)、RelativeLayout(相对布局)等。

Flutter 的布局 Widget 可以分成两类:

  • Single-child layout widgets(只有一个子元素)
  • Multi-child layout widgets(可以包含多个子元素)

Flutter 中所有的布局 Widget :

flutter.cn/docs/develo…

2.如何将可见 widget 添加到布局 widget

这个有点类似于 Android 原生开发中,将一个 View(或者 ViewGroup)添加到另一个 View(或者 ViewGroup)中。

在 Flutter 中,所有布局 widgets 都具有以下任一项:

  • 一个 child 属性,如果它们只包含一个子项 —— 例如 Center 和 Container。

  • 一个 children 属性,如果它们包含多个子项 —— 例如 Row、Column、ListView 和 Stack。

///Container 拥有一个 child 属性,所以我们可以为 Container 添加一个子元素,
///该子元素又可以包含自己的子元素,以此类推...
Container(
      padding: EdgeInsets.all(20),
      //在 Container 中通过 child 添加一个 Row Widget
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        //在 Row 种通过 children 添加多个 Icon Widget
        children: <Widget>[
            Icon(Icons.star, color: Colors.green[500]),
            Icon(Icons.star, color: Colors.green[500]),
            Icon(Icons.star, color: Colors.green[500]),
            Icon(Icons.star, color: Colors.black),
            Icon(Icons.star, color: Colors.black),
        ],
      ),
    )

3.State 的子类通常以下划线开头进行命名,表示它们的实现细节是私有的。如 Flutter 官方 Demo 工程里:

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

  final String title;

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

/// _MyHomePageState 是 State 的子类
///
/// 命名的时候以下划线开头表示私有
class _MyHomePageState extends State<MyHomePage> {
    ......
}

4.为了最大限度地减少高度嵌套的布局代码可能导致的视觉混乱,可以在变量和函数中实现 UI 的各个部分。

比如我想实现下图中红色框起来的 5 颗星星:

它的 widget 树形图如下:

//实现一个水平排列的 5 颗星星,并将它赋值给 starts,提供给其他 Widget 调用
var stars = Row(
  mainAxisSize: MainAxisSize.min,
  children: [
    Icon(Icons.star, color: Colors.green[500]),
    Icon(Icons.star, color: Colors.green[500]),
    Icon(Icons.star, color: Colors.green[500]),
    Icon(Icons.star, color: Colors.black),
    Icon(Icons.star, color: Colors.black),
  ],
);

final ratings = Container(
  padding: EdgeInsets.all(20),
  child: Row(
    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
    children: [
      //直接调用我们定义好的一个 widget
      stars,
      Text(
        '170 Reviews',
        style: TextStyle(
          color: Colors.black,
          fontWeight: FontWeight.w800,
          fontFamily: 'Roboto',
          letterSpacing: 0.5,
          fontSize: 20,
        ),
      ),
    ],
  ),
);

5.Flutter 中 MainAxisAlignment 和 CrossAxisAlignment

推荐阅读:Flutter中MainAxisAlignment和CrossAxisAlignment详解

6.DefaultTextStyle.merge()

//首先实现一个通用的 Style,并将它赋值给 descTextStyle
static var descTextStyle = TextStyle(
  color: Colors.black,
  fontWeight: FontWeight.w800,
  fontFamily: 'Roboto',
  letterSpacing: 0.5,
  fontSize: 18,
  height: 2,
);

// DefaultTextStyle.merge() 允许创建一个默认的文本样式,该文本样式由它的子元素和所有后续子元素继承。
// 也就是说 DefaultTextStyle.merge() 括号的里所有 Text Widget 的样式都统一为 descTextStyle。
final iconList = DefaultTextStyle.merge(
  style: descTextStyle,
  child: Container(
    padding: EdgeInsets.all(20),
    child: Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        Column(
          children: [
            Icon(Icons.kitchen, color: Colors.green[500]),
            Text('PREP:'),
            Text('25 min'),
          ],
        ),
        Column(
          children: [
            Icon(Icons.timer, color: Colors.green[500]),
            Text('COOK:'),
            Text('1 hr'),
          ],
        ),
        Column(
          children: [
            Icon(Icons.restaurant, color: Colors.green[500]),
            Text('FEEDS:'),
            Text('4-6'),
          ],
        ),
      ],
    ),
  ),
);

7.如何让子元素紧密组合在一起

比如像下图的星星一样,紧挨在一起:

方法:将其 mainAxisSize 设置为 MainAxisSize.min

Row(
  mainAxisSize: MainAxisSize.min,
  children: [
    Icon(Icons.star, color: Colors.green[500]),
    Icon(Icons.star, color: Colors.green[500]),
    Icon(Icons.star, color: Colors.green[500]),
    Icon(Icons.star, color: Colors.black),
    Icon(Icons.star, color: Colors.black),
  ],
)