在Flutter里面构建布局

2023-11-16

https://flutter.io/tutorials/layout/

finished lakes app that you'll build in 'Building a Layout'

可以学到:

Flutter的布局机制

如何水平与垂直布局控件

如何构建一个Flutter布局

布局的效果图:https://flutter.io/tutorials/layout/images/lakes.jpg

这篇指南,分步介绍了Flutter的布局方式,展示了如何在屏幕放一个控件.在介绍如何布局前,先来看一看包含的范围:

构建一个布局

如果想了解Flutter的布局机制,可以查看https://flutter.io/tutorials/layout/#approach

第0步:

设置环境,创建一个基础的Flutter应用.这一步不再赘述

添加一个图片到项目的顶层叫images.添加lage.jpg到这个目录中https://github.com/flutter/website/blob/master/_includes/code/layout/lakes/images/lake.jpg

更新pubspec.yaml文件,包含进assets

assets:

- images/lake.jpg

步骤1:

这步,分为以下几步:

确定行与列

布局是否包含网格

有没有遮罩的元素

ui是否需要tab

通知区域需要垂直定位,补白边框等

首先,确定最大元素.示例中,四个元素在一列,图片,两行,一个文本.

效果图:https://flutter.io/tutorials/layout/images/lakes-diagram.png

diagramming the rows in the lakes screenshot

两行内容的效果图:https://flutter.io/tutorials/layout/images/lakes-diagram.png

diagramming the widgets in the Title section

第一行,是标题,有三个子元素.一列文本,一个star图标,一个数字.第一列,包含两个文本,第一个文本有较大空间,需要折叠的.

第二行效果图:https://flutter.io/tutorials/layout/images/button-section-diagram.png

diagramming the widgets in the button section

按钮段,有三个元素,每一个子元素是一列,包含一个图标与文本.

一旦布局图形化,就很容易地自下而上的去实现它.

步骤2:实现标题行

先构建左侧的标题.将这一列放到可展开的控件中.让它充满这个剩下的空间.设置crossAxisAlignment属性到crossAxisAlignment.start行的开始位置.

将文本第一行放到一个容器中,添加padding.第二个子元素,也是文本,显示颜色是grey.

剩下的两个项是图标.为红色,文本为"41",将事先 行放到容器中,边的补白是32像素.

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

步骤3,实现按钮行

按钮行包含三个按钮,使用同样的布局.一个图标在文本上.

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

    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),

    //...
}

每一行几乎是确定的,可以很高效地创建内部方法.如buildButtonColumn(),它包含文本与图标.文字是主色

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

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

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

build方法,添加一个图标到列中,放一个文本到容器里,添加补白与图标分开.

行包含三个列.所以作为参数传入图标与文本.列在主轴方向,使用MainAxisAlignment.spaceEvenly来使它充满剩下的空间.

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

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

步骤4,实现文本段

定义文本段,将一个长文本定义一个变量.将它放入容器中,32像素的补白边.softwrap属性表明可折叠.

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    //...
    Widget textSection = Container(
      padding: const EdgeInsets.all(32.0),
      child: Text(
        '''
Lake Oeschinen lies at the foot of the Blüemlisalp in the Bernese Alps. Situated 1,578 meters above sea level, it is one of the larger Alpine Lakes. A gondola ride from Kandersteg, followed by a half-hour walk through pastures and pine forest, leads you to the lake, which warms to 20 degrees Celsius in the summer. Activities enjoyed here include rowing, and riding the summer toboggan run.
        ''',
        softWrap: true,
      ),
    );
  //...
}

步骤5:实现图标段

四列元素的三个已经完成了.剩下图片.图片获取比较慢,虽然它是通用的协议.步骤0已经添加了图片了.现在引用它.

在build最后

return MaterialApp(
//...
body: ListView(
  children: [
    Image.asset(
      'images/lake.jpg',
      height: 240.0,
      fit: BoxFit.cover,
    ),
    // ...
  ],
),
//...
);

步骤6,所有放一起

这些控件放到一个ListView,而不是一列中,因为ListView可以实现自己的滚动,特别是小屏上.

return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Top Lakes'),
        ),
        body: ListView(
          children: [
            Image.asset(
              'images/lake.jpg',
              width: 600.0,
              height: 240.0,
              fit: BoxFit.cover,
            ),
            titleSection,
            buttonSection,
            textSection,
          ],
        ),
      ),
    );
//...

代码地址:https://raw.githubusercontent.com/flutter/website/master/_includes/code/layout/lakes/main.dart

https://raw.githubusercontent.com/flutter/website/master/_includes/code/layout/lakes/pubspec.yaml

当热加载或编译运行时,就可以看到效果了.

 

Flutter的布局方式:

控件类用于构建ui

控件用于ui元素与布局.

组合简单的控件来构建复杂的控件.

Flutter的核心布局机制是控件.在Flutter,几乎所有的东西都是一个控件.甚至布局模型也是控件.图片,图标,文本是最常用的控件.你看不到的也是,像行,列,网格,约束等.

组合一个复杂的控件,像屏幕中展示的,左边三个图标,一个文本在下面的控件.https://flutter.io/tutorials/layout/images/lakes-icons.png

sample layout

https://flutter.io/tutorials/layout/images/lakes-icons-visual.png展示了可视化的布局,显示了各控件.

sample sample layout with visual debugging turned on

看一下控件树的图形:

https://flutter.io/tutorials/layout/images/sample-flutter-layout.png

node tree representing the sample layout

看到你效果,你可能会想容器.容器是一个控件,允许你自定义子控件.使用容器Container,要添加padding,margins,borders,或背景色.

示例中,文本控件放在容器中,有margins.整个行也有padding.

剩下的示例中 的ui,通过属性控制,使用color设置按钮的颜色.使用style属性来设置文本的字体,颜色,权重等.行列也有属性.可以设置垂直与水平方向的定位占比.

布局一个控件.

app本身也是一个控件

很容易创建控件与添加到布局中.

添加到布局中,显示在设备上

很容易使用Scaffold,它是Material组件库中的控件,提供默认的banner,背景色,有添加drawer,snackbar ,bottom sheets的api.

如果你喜欢,可以构建一个app,使用默认的库中的控件.

在Flutter如何布局一个单一的控件.这音展示如何创建一个简单的控件,然后展示在屏幕中.

就像hello world中一样,没太多需要介绍的

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(color: Colors.white),
      child: Center(
        child: Text('Hello World',
            textDirection: TextDirection.ltr,
            style: TextStyle(fontSize: 40.0, color: Colors.black87)),
      ),
    );
  }
}

效果图:https://flutter.io/tutorials/layout/images/hello-world.png

非Material的app没有appbar,标题,背景等.如果需要这些.可以自己加.

Material风格的:https://raw.githubusercontent.com/flutter/website/master/_includes/code/layout/hello-world/main.dart

只包含控件的:https://raw.githubusercontent.com/flutter/website/master/_includes/code/layout/widgets-only/main.dart

 

水平或垂直布局多个控件:

最常用的布局模式是将控件水平或垂直地排放.可以使用Row控件水平排放,使用Column控件垂直排放.

Row与Column是最常用的布局模式

Row与Column都有一个子控件列表.

子控件可以自己是一个Row或Column或其它复杂的控件.

可以同时指定子元素的垂直与水平位置

可以拉伸或约束子控件.

可以分配子元素如何使用空间.

内容:

在Flutter里面创建行或列,然后添加子元素列表到行或列控件中.下面展示如何嵌套

这个布局组织为一行,行包含两个子元素,一列在左,一个图标在右.https://flutter.io/tutorials/layout/images/pavlova-diagram.png

screenshot with callouts showing the row containing two children: a column and an image.

左侧是一个嵌套的控件.https://flutter.io/tutorials/layout/images/pavlova-left-column-diagram.png

diagram showing a left column broken down to its sub-rows and sub-columns

实现代码https://flutter.io/tutorials/layout/#nesting.

行列是基本的元素,这些低阶控件,允许你最大化地自定义.Flutter也提供了一些高阶的控件,来满足你的需求.如,可以使用ListTile来替代行,它是很容易使用的控件,有图标,三行文本.而取代列的有ListView,它自适应滚动.

排列控件

你使用mainAxisAlignment与crossAxisAlignment属性来控制着如何安排子元素.对于行,主轴是水平的.纵轴是垂直的.对于列则相反.

https://flutter.io/tutorials/layout/images/row-diagram.png,https://flutter.io/tutorials/layout/images/column-diagram.png

diagram showing the main axis and cross axis for a row diagram showing the main axis and cross axis for a column

接下来的示例中,三个图像是100像素宽,渲染框是大于300像素.所以设置主轴的排列是spaceEvenly,平分分割水平方向的空间.

appBar: AppBar(
  title: Text(widget.title),
),
body: Center(
  child: Row(
    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
    children: [
      Image.asset('images/pic1.jpg'),

https://flutter.io/tutorials/layout/images/row-spaceevenly-visual.png

列与行是一样的.

appBar: AppBar(
  title: Text(widget.title),
),
body: Center(
  child: Column(
    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
    children: [
      Image.asset('images/pic1.jpg'),

https://flutter.io/tutorials/layout/images/column-visual.png

代码:https://raw.githubusercontent.com/flutter/website/master/_includes/code/layout/column/main.dart

https://github.com/flutter/website/tree/master/_includes/code/layout/column/images

当一个布局太大了,会出现红色的条在边上.https://flutter.io/tutorials/layout/images/layout-too-large.png

a row that is too wide, showing a red string along the right edge

控件可以缩放来适应,这时要使用Expanded控件.

对控件缩放大小

如果你的控件是两倍于兄弟控件的大小.可以放到Expanded控件中,控件着它的主轴方向的大小.它有flex属性,是整型值,测量flex因子.默认是1.这就像weight一样.

appBar: AppBar(
  title: Text(widget.title),
),
body: Center(
  child: Row(
    crossAxisAlignment: CrossAxisAlignment.center,
    children: [
      Expanded(
        child: Image.asset('images/pic1.jpg'),
      ),
      Expanded(
        flex: 2,
        child: Image.asset('images/pic2.jpg'),
      ),
      Expanded(

效果:https://flutter.io/tutorials/layout/images/row-expanded-visual.png

三个元素,中间是旁边的两倍大小,所以flex:2

当空间太大,会有红色的边框,https://flutter.io/tutorials/layout/images/row-expanded-2-visual.png,放到Expanded就可以了

打包控件

默认的行与列会尽量占用主轴的空间.如果你要打包起来,就设置mainAxisSize到最小MainAxisSize.min.

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    var packedRow = 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),
      ],
    );

  // ...
}

https://flutter.io/tutorials/layout/images/packed.png 这种就是居中显示,所有控件向中间靠拢.它不像android里的居中定位,所以是通过设置轴上的属性来实现的

a row of 3 images with the middle image twice as wide as the others

嵌套的列与行

布局框架,允许你嵌套行与列,只要你喜欢.https://flutter.io/tutorials/layout/images/pavlova-large-annotated.png

a screenshot of the pavlova app, with the ratings and icon rows outlined in red

概述章节为两行实现的.rating行由五个星图标实现.图标行,包含三列图与文本.

rating行的控件树:https://flutter.io/tutorials/layout/images/widget-tree-pavlova-rating-row.png

a node tree showing the widgets in the ratings row

rating变量,创建一个行,包含五个星图标.与文本

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

    var ratings = Container(
      padding: EdgeInsets.all(20.0),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              Icon(Icons.star, color: Colors.black),
              Icon(Icons.star, color: Colors.black),
              Icon(Icons.star, color: Colors.black),
              Icon(Icons.star, color: Colors.black),
              Icon(Icons.star, color: Colors.black),
            ],
          ),
          Text(
            '170 Reviews',
            style: TextStyle(
              color: Colors.black,
              fontWeight: FontWeight.w800,
              fontFamily: 'Roboto',
              letterSpacing: 0.5,
              fontSize: 20.0,
            ),
          ),
        ],
      ),
    );
    //...
  }
}

它的下面,包含三列.每一列包含一个图标与两行文本.控件树:https://flutter.io/tutorials/layout/images/widget-tree-pavlova-icon-row.png

a node tree for the widets in the icons row

iconList变量定义在icons行中

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

    var descTextStyle = TextStyle(
      color: Colors.black,
      fontWeight: FontWeight.w800,
      fontFamily: 'Roboto',
      letterSpacing: 0.5,
      fontSize: 18.0,
      height: 2.0,
    );

    // DefaultTextStyle.merge allows you to create a default text
    // style that is inherited by its child and all subsequent children.
    var iconList = DefaultTextStyle.merge(
      style: descTextStyle,
      child: Container(
        padding: EdgeInsets.all(20.0),
        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'),
              ],
            ),
          ],
        ),
      ),
    );
    // ...
  }
}

leftColumn变量,包含rating图标.

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

    var leftColumn = Container(
      padding: EdgeInsets.fromLTRB(20.0, 30.0, 20.0, 20.0),
      child: Column(
        children: [
          titleText,
          subTitle,
          ratings,
          iconList,
        ],
      ),
    );
    //...
  }
}

leftColumn放在容器中,宽受约束,整个ui放在一个卡片里.

使用Image.network来内嵌图片,但这个示例图片是放在images目录中的.并添加到pubspec文件里.

body: Center(
  child: Container(
    margin: EdgeInsets.fromLTRB(0.0, 40.0, 0.0, 30.0),
    height: 600.0,
    child: Card(
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Container(
            width: 440.0,
            child: leftColumn,
          ),
          mainImage,
        ],
      ),
    ),
  ),
),

代码:https://raw.githubusercontent.com/flutter/website/master/_includes/code/layout/pavlova/main.dart

图片:https://github.com/flutter/website/tree/master/_includes/code/layout/pavlova/images

配置:https://raw.githubusercontent.com/flutter/website/master/_includes/code/layout/pavlova/pubspec.yaml

通用布局控件:

Flutter有丰富的布局控件,有一些比较常用.https://docs.flutter.io/文档可以查到更多关于控件的使用.这些控件主要是让用户可以容易地实现需求.

控件,分为两类,普通的控件与Material设计库.但只有Material的app可以使用Material库.

Standard widgets

  • Container

    Adds padding, margins, borders, background color, or other decorations to a widget.

  • GridView

    Lays widgets out as a scrollable grid.

  • ListView

    Lays widgets out as a scrollable list.

  • Stack

    Overlaps a widget on top of another.

Material Components

  • Card

    Organizes related info into a box with rounded corners and a drop shadow.

  • ListTile

    Organizes up to 3 lines of text, and optional leading and trailing icons, into a row.

容器:

很多布局,大量使用容器来分割控件,这些容器带有边框,空白等.通过将整个布局放在容器中,可以修改设备的背景色.

容器总结:

添加padding,margin,border

改变背景色

包含单一的控件,可以是行,列或根

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

容器示例

可以在https://github.com/flutter/flutter/tree/master/examples/flutter_gallery中查找到使用的示例.

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

这个布局包含一个列,每列两行,有两个图片,每个图片,包含灰边与间距,列使用容器来设置背景色.

代码:https://raw.githubusercontent.com/flutter/website/master/_includes/code/layout/container/main.dart

图片:https://github.com/flutter/website/tree/master/_includes/code/layout/container/images

配置:https://raw.githubusercontent.com/flutter/website/master/_includes/code/layout/container/pubspec.yaml

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

    var container = Container(
      decoration: BoxDecoration(
        color: Colors.black26,
      ),
      child: Column(
        children: [
          Row(
            children: [
              Expanded(
                child: Container(
                  decoration: BoxDecoration(
                    border: Border.all(width: 10.0, color: Colors.black38),
                    borderRadius:
                        const BorderRadius.all(const Radius.circular(8.0)),
                  ),
                  margin: const EdgeInsets.all(4.0),
                  child: Image.asset('images/pic1.jpg'),
                ),
              ),
              Expanded(
                child: Container(
                  decoration: BoxDecoration(
                    border: Border.all(width: 10.0, color: Colors.black38),
                    borderRadius:
                        const BorderRadius.all(const Radius.circular(8.0)),
                  ),
                  margin: const EdgeInsets.all(4.0),
                  child: Image.asset('images/pic2.jpg'),
                ),
              ),
            ],
          ),
          // ...
          // See the definition for the second row on GitHub:
          // https://raw.githubusercontent.com/flutter/website/master/_includes/code/layout/container/main.dart
        ],
      ),
    );
    //...
  }
}

网格:

GridView是二维的列表.当它太大时,会自己滚动.可以使用预设也可以自定义.

总结:

网格外放控件

检测到列超过渲染框时提供滚动.

有两个构建方式.GridView.count允许几列.GridView.extent允许最大宽像素.

a 3-column grid of photosa 2 column grid with footers containing titles on a partially translucent background

代码:https://raw.githubusercontent.com/flutter/website/master/_includes/code/layout/grid/main.dart

代码:https://github.com/flutter/flutter/blob/master/examples/flutter_gallery/lib/demo/material/grid_list_demo.dart

// 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 List<Container>.generate(
      count,
      (int index) =>
          Container(child: Image.asset('images/pic${index+1}.jpg')));
}

Widget buildGrid() {
  return 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 Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: buildGrid(),
      ),
    );
  }
}

列表:列表是一个列的控件,当内容超过渲染框时自动滚动

总结:一个特定box的列表

可以水平或垂直布局

超过渲染框范围会自动滚动.

比Column更容易实现滚动.配置更少.

列表示例:

a ListView containing movie theaters and restaurants

代码:https://raw.githubusercontent.com/flutter/website/master/_includes/code/layout/listview/main.dart

gallery代码示例:https://github.com/flutter/flutter/blob/master/examples/flutter_gallery/lib/demo/colors_demo.dart

List<Widget> list = <Widget>[
  ListTile(
    title: Text('CineArts at the Empire',
        style: TextStyle(fontWeight: FontWeight.w500, fontSize: 20.0)),
    subtitle: Text('85 W Portal Ave'),
    leading: Icon(
      Icons.theaters,
      color: Colors.blue[500],
    ),
  ),
  ListTile(
    title: Text('The Castro Theater',
        style: TextStyle(fontWeight: FontWeight.w500, fontSize: 20.0)),
    subtitle: Text('429 Castro St'),
    leading: Icon(
      Icons.theaters,
      color: Colors.blue[500],
    ),
  ),
  // ...
  // See the rest of the column defined on GitHub:
  // https://raw.githubusercontent.com/flutter/website/master/_includes/code/layout/listview/main.dart
];

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

栈:

使用栈来排列控件.通常是在顶部的 图片上使用.这个控件可以部分或全部浮在基础控件上.

在悬浮另一个控件上使用.

列表中的第一个元素,是一个基础擦伤,然后第二个在上面.

栈的内容不可滚动.

可以选择是否切割来显示超过部分.

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

代码:https://raw.githubusercontent.com/flutter/website/master/_includes/code/layout/stack/main.dart

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

卡片:

卡片是Material组件库中的,可以组合几乎所有控件.但它经常与ListTile一起使用.卡片是有单一的子元素.这个子元素可 以是行,或,列表,网格.默认的卡片是0*0像素,可以使用SizedBox来约束大小.

在Flutter,卡片特性有圆角与阴影,像3d效果.改变卡片的elevation属性,允许你控制阴影效果.这点像Android里面的一样.查看https://material.io/guidelines/material-design/elevation-shadows.html可以知道支持的属性.

总结:

来自于Material设计.实现了Material卡片

像砖块的形式展现

接受单一的子元素,子元素可以包含各种控件.

带有圆角与阴影边

不可滚动.

示例:

a Card containing 3 ListTiles

代码:https://raw.githubusercontent.com/flutter/website/master/_includes/code/layout/card/main.dart

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

ListTile

使用ListTile作为一个定制化的行控件,来自Material库,可以容易地创建一三行文本,一个可选的首尾图标.它经常与卡片与ListView共用.

示例:a Card containing 3 ListTiles

代码:https://flutter.io/tutorials/layout/#card-examples

资源:

下面的资源帮助你编写布局:

 

翻译的不太好.像其它框架一个,react,weex,一切都是控件,然后用这些控件去拼接起来,整体上会比单独在Android或ios上要复杂一点.布局中,使用的是轴的概念,因为允许垂直与水平方向的.基于目前的ide与插件,开发比较耗事,无法预览是个问题, 但ios开发人员可能比较容易适应它.Android习惯了xml布局会有些迷茫,整体思路都类似的.控件就是上下左右摆放,然后设置一些间距等.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在Flutter里面构建布局 的相关文章

  • 双系统卸载Linux,重装Deepin

    卸载掉之前的Linux系统 参考资料 https www bilibili com video av209430195 下载diskgenius https www diskgenius cn download php 删除Linux分区
  • StackExchange.Redis Timeout performing 超时问题

    最近在做的一个项目 用的 net core 2 1 然后缓存用的Redis 缓存相关封装是同事写的 用的驱动是StackExchange Redis version 2 0 571 一直听说这个驱动并发情况下有TimeOut bug 项目开
  • Flutter--Button浅谈

    作为一个常用到不能再常用的组件 material库中的button组件都有一点奇怪 存在无法设置的内外边距 我们做一个简单的展示 选几个常见button 统一使用Text做child 外加一个带红色的Container组件 观察margin
  • JavaScript-1-100之间整数的和

    要求 求1 100之间整数的和 实现代码
  • 图像数据库

    ImageNet ImageNet是一个计算机视觉系统识别项目 是目前世界上图像识别最大的数据库 是美国斯坦福的计算机科学家李飞飞模拟人类的识别系统建立的 能够从图片识别物体 目前已经包含14197122张图像 是已知的最大的图像数据库 每
  • $(this).parent("tr").find("td").eq(0).text()

    this parent tr find td eq 0 text
  • 新年新气象---多数据源配置

    概述 2022年第一天 在这祝大家新年快乐 好运连连 事业爱情双丰收 本文主要是通过注解结合aop的方式实现多数据源的动态切换 一 配置文件 spring datasource type com alibaba druid pool Dru
  • 增强现实-实验一

    实验一 1 手工制作一个空间增强现实盒子 如示例所示 放置在平板或手机屏幕上 搭配应用实现立体投影效果 2 制作立体投影所需的视频 程序 unity 全息投影 伪 视频 盒子蛮好做的主要是视频 之前没接触过unity 研究了一番 首先设置四
  • 关于js操作cookie

    一 什么是cookie 我们在浏览器中 经常涉及到数据的交换 比如你登录邮箱 登录一个页面 我们经常会在此时设置30天内记住我 或者自动登录选项 那么它们是怎么记录信息的呢 答案就是今天的主角cookie了 Cookie是由HTTP服务器设
  • 修饰符-访问修饰符internal sealed

    摘自 internal C 参考 摘自 sealed C 参考 Internal 访问仅限于当前程序集 protected internal 访问限制到当前程序集或从包含派生的类型的类别 程序集就是代码编译后bin目录下生产的 exe或者
  • 16-DFS(深度优先搜索算法)

    DFS 深度优先算法 是常见的搜索算法 早期常用于需要搜索的地方 并且还拓展出很多其它算法 深度优先算法 DFS DFS 深度优先算法 是早期开发爬虫时常用的算法 它的搜索思路是从树根开始一直找直到找到树型数据结构的叶节点 以搜索一个节点数
  • 小程序iOS兼容问题总结

    1 IOS 上 JS 只支持 new Date YYYY MM DD 这一种格式 YYYY MM DD 等格式都不支持
  • Raft 一致性算法

    文章目录 1 CAP 定理 1 Raft 基本概念 2 Raft 算法核心 2 1 Leader 选举 2 2 日志复制 3 总结 1 CAP 定理 文章参考 lt 零声教育 gt 的C C linux服务期高级架构系统教程学习 服务器高级
  • POI框架导出EXCEL的简单列子(跨行跨列)合并单元格

    public static void main String args throws IOException try HSSFWorkbook wb new HSSFWorkbook HSSFSheet sheet wb createShe
  • 十八. Kubernetes Ingress

    目录 一 Ingress 基础解释 二 ingressController 安装 六 ingress 使用示例 pathType 详细 annotations 基于k8s注解为 nginx 添加功能示例 路径重写 Session Affin
  • (二)selenium IDE 插件下载与安装

    前面selenium已经下载安装成功 接下来尝试录制下脚本 此时有个IDE插件是必备的 1 下载Chrome插件 进入网址 https www extfans com 搜索 selenium IDE 然后下载 2 安装插件 打开Chrome
  • plsql 返回结果集的存储过程

    返回结果集的存储过程 1 创建一个包 在该包中定义了一个游标类型test corsor create or replace package testpackage as type test cursor is ref cursor end
  • Linux内核自带SPI设备驱动测试程序分析:spidev_test.c

    在Linux系统中 SPI 的用户模式设备接口的驱动源码位于 drivers spi spidev c 在应用层生成 dev spidev 的节点 可以通过 read write 达到与硬件设备的 SPI 通信 下面介绍spidev驱动移植
  • js获取当前月、上一月和下一月

    获得当前月 function getNowMonth var date new Date var year date getFullYear var month date getMonth 1 month month gt 9 month

随机推荐

  • K8S 基础概念学习

    1 K8S 通过Deployment 实现滚动发布 比如左边的ReplicatSet 的 pod 中 是V1版本的镜像 Deployment通过 再启动一个 ReplicatSet 中启动 pod中 镜像就是V2 2 每个pod 中都有一个
  • 渗透测试工程师面试题大全(二)

    渗透测试工程师面试题大全 二 from backlion大佬 整理 51 sql 注入写文件都有哪些函数 1 select 一句话 into outfile 路径 2 select 一句话 into dumpfile 路径 3 select
  • 如何安装 IntelliJ IDEA 最新版本——详细教程

    IntelliJ IDEA 简称 IDEA 被业界公认为最好的 Java 集成开发工具 尤其在智能代码助手 代码自动提示 代码重构 代码版本管理 Git SVN Maven 单元测试 代码分析等方面有着亮眼的发挥 IDEA 产于捷克 开发人
  • Allure在自动化测试中的应用!

    01 Allure的简介及使用 1 应用场景 自动化的结果一定是通过一个报告来进行体现 Allure 是一个独立的报告插件 生成美观易读的报告 目前支持Python Java PHP C 等语言 为dev QA 提供详尽的测试报告 测试步骤
  • 微信小程序实现视频号跳转

    三种类型 1 跳转到视频号主页 wx openChannelsUserProfile finderUserName 视频号id 2 跳转到视频号视频 wx openChannelsActivity feedId 视频id finderUse
  • 文件上传-图片webshell上传

    图片webshell制作 在服务器端的PHP代码中 对于用户上传的文件做文件类型检查 查看文件格式是否符合上传规范 可以检查文件二进制格式的前几个字节 从而判断文件类型是否正确 针对这种情况可以直接新建要给1 jpg 其中代码内容如下 GI
  • 【数据结构】 二叉树面试题讲解->壹

    文章目录 引言 相同的树 https leetcode cn problems same tree description 题目描述 示例 示例一 示例二 示例三 题目解析 代码实现 另一棵树的子树 https leetcode cn pr
  • 华为OD机试-找出重复代码-2022Q4 A卷-Py/Java/JS

    小明负责维护项目下的代码 需要查找出重复代码 用以支撑后续的代码优化 请你帮助小明找出重复的代码 重复代码查找方法 以字符串形式给出两行代码 字符审长度1 lt length lt 100 由英文字母 数字和空格组成 找出两行代码中的最长公
  • 深度学习之感知器的python实现,及用感知器实现鸢尾花的分类

    机器学习一般用来处理结构化的数据 深度学习一般用来处理非结构化的数据 例如图像 视频 文字等 权重更新过程 如果真实是1 预测是0 则权重会增加 相当于为了达到阈值增加权重 如果真实是0 预测是1 则权重会降低 相当于为了达到阈值减少权重
  • 玩客云通过openwrt作为旁路由

    前置条件 玩客云安装 docker 安装 OpenWrt 这边又两套方案可供选择 下面是具体教程的链接镜像一 https www right com cn forum thread 8024126 1 1 html镜像二 https hub
  • 在Idea中调试ant应用

    Ant调试 Ant调试 ant 是一种非常方便的打包 部署的工具 通过ant 可以一键构建整个项目 虽然MVN也支持这种功能 但是MVN混杂了package管理的功能 并且不是很自由 学习成本比较高 通常 我们调试ant构成的程序 是通过远
  • 零散算法

    1 字符串匹配 朴素的串匹配算法 KMP匹配算法 2 广度优先搜索BFS 3 深度优先搜索DFS 4 狄克斯特拉算法Dijkstra 5 贪婪算法 6 动态规划 7 安全散列算法SHA 用递归分析问题 基于循环写代码 10 关于查找算法 1
  • unity+射线检测

    private Camera aRCamera Ray ray RaycastHit hit aRCamera GameObject Find RenderCamera GetComponent
  • JavaScript节流与防抖

    一 节流 概念 在规定的间隔时间范围内不会重复触发回调 只有大于这个时间间隔才会触发回调 把频繁触发变为少量触发 类似于技能CD 应用 点击按钮 轮播图点击左右箭头 插件lodash js 它里面封装了函数的防抖与节流业务 p 计数器 sp
  • 抓包工具篇|Charles

    1 简介 Charles 是在 Mac 下常用的网络封包截取工具 在做 移动开发时 我们为了调试与服务器端的网络通讯协议 常常需要截取网络封包来分析 Charles 是收费软件 可以免费试用 30 天 试用期过后 未付费的用户仍然可以继续使
  • 怎样使用BAT脚本实现自动按键盘的某个键

    批处理是不行的 用VBS 很简单 例子如下 Set objShell CreateObject Wscript Shell do WScript Sleep 3000 objShell SendKeys F5 WScript Sleep 3
  • Weblogic 12c 集群部署和session复制

    在上一篇Weblogic12c集群搭建的基础上 这一篇介绍Weblogic12c集群应用的部署和session复制 1 启动服务 首先在weblogic12c控制台 启动受托管服务server1 server2 server3 2 将要部署
  • 前端实现微信支付(H5,微信小程序)

    一 微信支付 H5 微信小程序 通常一些电商项目使用到微信支付操作 所以简单地介绍一下微信支付的具体流程 1 1 什么是微信支付 在什么业务场景会使用到微信支付 微信支付是微信内置微信浏览器 其他浏览器不支持 或者微信小程序的支付接口 主要
  • ubuntu如何修改首次登入不是anaconda的base环境

    ubuntu安装anaconda后 每次用户登录进去后所在环境都是anaconda的base虚拟环境 如果用户不想一开始登进去就是anaconda的base环境 想在需要使用anaconda时再激活anaconda环境 输入下面的命令就可以
  • 在Flutter里面构建布局

    https flutter io tutorials layout 可以学到 Flutter的布局机制 如何水平与垂直布局控件 如何构建一个Flutter布局 布局的效果图 https flutter io tutorials layout