阅读(2154) (0)

Flutter 常用布局widgets

2020-02-04 11:36:05 更新

Flutter拥有丰富的布局widget,但这里有一些最常用的布局widget。其目的是尽可能快地让您构建应用并运行,而不是让您淹没在整个完整的widget列表中。 

以下widget分为两类:widgets library中的标准widget和Material Components library中的专用widget 。 任何应用程序都可以使用widgets library中的widget,但只有Material应用程序可以使用Material Components库。


标准 widgets

  • Container添加 padding, margins, borders, background color, 或将其他装饰添加到widget.
  • GridView将 widgets 排列为可滚动的网格.
  • ListView将widget排列为可滚动列表
  • Stack将widget重叠在另一个widget之上.


Material Components

  • Card将相关内容放到带圆角和投影的盒子中。
  • ListTile将最多3行文字,以及可选的行前和和行尾的图标排成一行


Container

许多布局会自由使用容器来使用padding分隔widget,或者添加边框(border)或边距(margin)。您可以通过将整个布局放入容器并更改其背景颜色或图片来更改设备的背景。


Container 概要 :

  • 添加padding, margins, borders
  • 改变背景颜色或图片
  • 包含单个子widget,但该子widget可以是Row,Column,甚至是widget树的根

a diagram showing that margins, borders, and padding, that surround content in a container

Container 示例:

除了下面的例子之外,本教程中的许多示例都使用了Container。 您还可以在Flutter Gallery中找到更多容器示例。

该布局中每个图像使用一个Container来添加一个圆形的灰色边框和边距。然后使用容器将列背景颜色更改为浅灰色。

Dart code: main.dart, snippet belowImages: imagesPubspec: pubspec.yaml

a screenshot showing 2 rows, each containing 2 images; the images have grey rounded borders, and the background is a lighter grey

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {

    var container = new Container(
      decoration: new BoxDecoration(
        color: Colors.black26,
      ),
      child: new Column(
        children: [
          new Row(
            children: [
              new Expanded(
                child: new Container(
                  decoration: new BoxDecoration(
                    border: new Border.all(width: 10.0, color: Colors.black38),
                    borderRadius:
                        const BorderRadius.all(const Radius.circular(8.0)),
                  ),
                  margin: const EdgeInsets.all(4.0),
                  child: new Image.asset('images/pic1.jpg'),
                ),
              ),
              new Expanded(
                child: new Container(
                  decoration: new BoxDecoration(
                    border: new Border.all(width: 10.0, color: Colors.black38),
                    borderRadius:
                        const BorderRadius.all(const Radius.circular(8.0)),
                  ),
                  margin: const EdgeInsets.all(4.0),
                  child: new Image.asset('images/pic2.jpg'),
                ),
              ),
            ],
          ),
        ],
      ),
    );
    //...
  }
}


GridView

使用GridView将widget放置为二维列表。 GridView提供了两个预制list,或者您可以构建自定义网格。当GridView检测到其内容太长而不适合渲染框时,它会自动滚动。

GridView 概览:

  • 在网格中放置widget
  • 检测列内容超过渲染框时自动提供滚动
  • 构建您自己的自定义grid,或使用一下提供的grid之一:GridView.count 允许您指定列数GridView.extent 允许您指定项的最大像素宽度

注意: 在显示二维列表时,重要的是单元格占用哪一行和哪一列时, 应该使用Table或 DataTable。

GridView 示例:

a 3-column grid of photos

使用GridView.extent 创建最大宽度为150像素的网格Dart code: main.dart, snippet belowImages: imagesPubspec: pubspec.yaml

a 2 column grid with footers containing titles on a partially translucent background

使用GridView.count 在纵向模式下创建两个行的grid,并在横向模式下创建3个行的网格。通过为每个GridTile设置footer属性来创建标题。Dart code: grid_list_demo.dart from the Flutter Gallery

// The images are saved with names pic1.jpg, pic2.jpg...pic30.jpg.
// The List.generate constructor allows an easy way to create
// a list when objects have a predictable naming pattern.

List<Container> _buildGridTileList(int count) {

  return new List<Container>.generate(
      count,
      (int index) =>
          new Container(child: new Image.asset('images/pic${index+1}.jpg')));
}

Widget buildGrid() {
  return new GridView.extent(
      maxCrossAxisExtent: 150.0,
      padding: const EdgeInsets.all(4.0),
      mainAxisSpacing: 4.0,
      crossAxisSpacing: 4.0,
      children: _buildGridTileList(30));
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new Center(
        child: buildGrid(),
      ),
    );
  }
}


ListView

ListView是一个类似列的widget,它的内容对于其渲染框太长时会自动提供滚动。

ListView 摘要:

  • 用于组织盒子中列表的特殊Column
  • 可以水平或垂直放置
  • 检测它的内容超过显示框时提供滚动
  • 比Column配置少,但更易于使用并支持滚动

ListView 示例:

a ListView containing movie theaters and restaurants

使用ListView显示多个ListTile的业务列表。分隔线将剧院与餐厅分开

Dart code: main.dart, snippet belowIcons: Icons classPubspec: pubspec.yaml

a ListView containing shades of blue from the Material Design color palette

使用ListView控件来显示Material Design palette中的ColorsDart code: Flutter Gallery中的 colors_demo.dart

List<Widget> list = <Widget>[
  new ListTile(
    title: new Text('CineArts at the Empire',
        style: new TextStyle(fontWeight: FontWeight.w500, fontSize: 20.0)),
    subtitle: new Text('85 W Portal Ave'),
    leading: new Icon(
      Icons.theaters,
      color: Colors.blue[500],
    ),
  ),
  new ListTile(
    title: new Text('The Castro Theater',
        style: new TextStyle(fontWeight: FontWeight.w500, fontSize: 20.0)),
    subtitle: new Text('429 Castro St'),
    leading: new Icon(
      Icons.theaters,
      color: Colors.blue[500],
    ),
  ),
];

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      // ...
      body: new Center(
        child: new ListView(
          children: list,
        ),
      ),
    );
  }
}


Stack

使用Stack来组织需要重叠的widget。widget可以完全或部分重叠底部widget。

Stack summary:

  • 用于与另一个widget重叠的widget
  • 子列表中的第一个widget是base widget; 随后的子widget被覆盖在基础widget的顶部
  • Stack的内容不能滚动
  • 您可以选择剪切超过渲染框的子项

Stack 示例:

a circular avatar containing the label 'Mia B' in the lower right portion of the circle

使用Stack叠加Container(在半透明的黑色背景上显示其文本),放置在Circle Avatar的顶部。Stack使用alignment属性和调整文本偏移。Dart code: main.dart, snippet belowImage: imagesPubspec: pubspec.yaml

an image with a grey gradient across the top; on top of the gradient is tools painted in white

使用Stack将gradient叠加到图像的顶部。gradient确保工具栏的图标与图片不同。Dart code: contacts_demo.dart

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    var stack = new Stack(
      alignment: const Alignment(0.6, 0.6),
      children: [
        new CircleAvatar(
          backgroundImage: new AssetImage('images/pic.jpg'),
          radius: 100.0,
        ),
        new Container(
          decoration: new BoxDecoration(
            color: Colors.black45,
          ),
          child: new Text(
            'Mia B',
            style: new TextStyle(
              fontSize: 20.0,
              fontWeight: FontWeight.bold,
              color: Colors.white,
            ),
          ),
        ),
      ],
    );
    // ...
  }
}


Card

Material Components 库中的Card包含相关内容块,可以由大多数类型的widget构成,但通常与ListTile一起使用。Card有一个子项, 但它可以是支持多个子项的列,行,列表,网格或其他小部件。默认情况下,Card将其大小缩小为0像素。您可以使用SizedBox来限制Card的大小。

在Flutter中,Card具有圆角和阴影,这使它有一个3D效果。更改Card的elevation属性允许您控制投影效果。 例如,将elevation设置为24.0,将会使Card从视觉上抬离表面并使阴影变得更加分散。 有关支持的elevation值的列表,请参见Material guidelines中的Elevation and Shadows。 如果指定不支持的值将会完全禁用投影 。

Card 摘要:

  • 实现了一个 Material Design card
  • 接受单个子项,但该子项可以是Row,Column或其他包含子级列表的widget
  • 显示圆角和阴影
  • Card内容不能滚动
  • Material Components 库的一个widget

Card 示例:

a Card containing 3 ListTiles 包含3个ListTiles并通过用SizedBox包装进行大小调整的Card。分隔线分隔第一个和第二个ListTiles。Dart code: main.dart, snippet belowIcons: Icons classPubspec: pubspec.yaml

a Card containing an image and text and buttons under the image

包含图像和文字的CardDart code: cards_demo.dart from the Flutter Gallery

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    var card = new SizedBox(
      height: 210.0,
      child: new Card(
        child: new Column(
          children: [
            new ListTile(
              title: new Text('1625 Main Street',
                  style: new TextStyle(fontWeight: FontWeight.w500)),
              subtitle: new Text('My City, CA 99984'),
              leading: new Icon(
                Icons.restaurant_menu,
                color: Colors.blue[500],
              ),
            ),
            new Divider(),
            new ListTile(
              title: new Text('(408) 555-1212',
                  style: new TextStyle(fontWeight: FontWeight.w500)),
              leading: new Icon(
                Icons.contact_phone,
                color: Colors.blue[500],
              ),
            ),
            new ListTile(
              title: new Text('costa@example.com'),
              leading: new Icon(
                Icons.contact_mail,
                color: Colors.blue[500],
              ),
            ),
          ],
        ),
      ),
    );
  //...
}


ListTile

ListTile是Material Components库中的一个专门的行级widget,用于创建包含最多3行文本和可选的行前和行尾图标的行。ListTile在Card或ListView中最常用,但也可以在别处使用。

ListTile 摘要:

  • 包含最多3行文本和可选图标的专用行
  • 比起Row不易配置,但更易于使用
  • Material Components 库里的widget

ListTile 示例:

a Card containing 3 ListTiles

包含3个ListTiles的CardDart code: See Card examples.

3 ListTiles, each containing a pull-down button

使用ListTile列出3个下拉按钮类型。Dart code: buttons_demo.dart from the Flutter Gallery