Flutter探索(二)--- Flutter的布局

  • Flutter 探索学习目录

Flutter 中的Widgets

  • Widgets 是用于构建 UI 的类。
  • Widgets 可以用于布局和展示 UI 元素。
  • 通过组合简单的widgets 来构建复杂的widgets
1、创建一个简单的Widget

创建一个Text Widget,

Text('Hello world')

创建一个IconButton Widget,

IconButton(icon: Icon(Icons.search), onPressed: null)
2、将可见 widget 添加到布局 widget

两个widget相互组合成一个复合widget:例如:
Text widget 添加进 Center widget

Center(
  child: Text('Hello World'),
),

关于childchildren

  • child 属性,只包含一个子项 —— 一般用于 CenterContainer
  • children 属性,如果它们包含多个子项 —— 一般用于RowColumnListViewStack
3、将布局 widget 添加到页面

一个 Flutter app 本身就是一个 widget,大多数 widgets 都有一个build() 方法,在 appbuild() 方法中实例化和返回一个 widget 会让它显示出来
Widget 布局一般有两种情况Material非 Material

  • 使用Material布局app
  • Material 库 实现了一些遵循Material Design 原则的 widgets。在设计 UI 时,你可以只使用标准 widgets 库 中的 widgets,也可以使用 Material library 中的 widgets。你可以混合来自两个库的 widgets,可以自定义现有 widgets,也可以构建自己的一组自定义 widgets
  • 可以使用 Scaffold widget,它提供默认的 banner、背景颜色,还有用于添加抽屉、提示条和底部列表弹窗的 API。你可以将 Center widget 直接添加到主页body 的属性中
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter layout demo',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter layout demo'),
        ),
        body: Center(
          child: Text('Hello World'),
        ),
      ),
    );
  }
}
  • Material布局
    Material布局 app,你可以将 Center widget 添加到appbuild() 方法里,默认不包含 AppBar、标题和背景颜色。如果你希望在非 Material app 中使用这些功能,则必须自己构建它们
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: 32,
            color: Colors.black87,
          ),
        ),
      ),
    );
  }
}
4、横向或纵向布局多个 widgets

在Flutter里面我们常用Row 和 Column来进行 水平和 垂直排列。

  • Row 水平排列
body: Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          Image.asset('assets/pic1.jpg'),
          Image.asset('assets/pic2.jpg'),
        ],
      ),

在这里插入图片描述

  • Column 垂直排列
body: Column(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          Image.asset('assets/pic1.jpg'),
          Image.asset('assets/pic2.jpg'),![在这里插入图片描述](https://img-blog.csdnimg.cn/2021010714540372.png)

        ],
      ),

在这里插入图片描述

  • Widgets 对齐
    水平垂直的布局中,我么可以使用mainAxisAlignmentcrossAxisAlignment属性控制如何对齐其子项。
    对于来说,主轴水平延伸,交叉轴垂直延伸。
    对于来说,主轴垂直延伸,交叉轴水平延伸。
    Flutter探索(二)--- Flutter的布局_第1张图片

MainAxisAlignmentCrossAxisAlignment类为控制对齐提供了各种常量

enum MainAxisAlignment {
  // start  end 
  // 将子级放置在尽可能靠近主轴起点的位置
  // Row:用于确定起点是左侧还是右侧
  // Column: 用于确定起点是顶部还是底部
  start,
  end,
  // 将子对象尽可能靠近主轴中间
  center,
  //将空白区域放在里两个子视图之间
  spaceBetween,
  //在子视图之间以及第一个和最后一个子视图之前和之后的一半空间之间均匀地放置可用空间。
  spaceAround,
  ///将空闲空间均匀地放在子视图之间以及第一个和最后一个子视图之前和之后
  spaceEvenly,
}


enum CrossAxisAlignment {
  // start  end 
  //将子项的起始边缘与交叉轴的起始侧对齐
  // Row:用于确定起点是左侧还是右侧
  // Column: 用于确定起点是顶部还是底部
  start, 
  end,
  // 放置子项,使其中心与十字轴的中心对齐
  // 默认的
  center,
  // 将子对象填充交叉轴
  // 这会导致传递给子级的约束在交叉轴上很紧。
  stretch,
  // 将子项沿着横轴放置,使其基线匹配
  baseline,
}

使用列子:

Row(
  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  children: [
    Image.asset('images/pic1.jpg'),
    Image.asset('images/pic2.jpg'),,
  ],
);
  • Widgets 调整大小
    我么可以通过使用 Expandedwidget ,可以调整 widgets 的大小以适合行或列, Expanded里面有个flex属性,这是一个用来确定widget弹性系数的整数。默认的弹性系数为 1 ,我们可以更改这个属性来调整每个widgets的大小
Row(
  crossAxisAlignment: CrossAxisAlignment.center,
  children: [
    Expanded(
      child: Image.asset('images/pic1.jpg'),
    ),
    Expanded(
      flex: 2,
      child: Image.asset('images/pic2.jpg'),
    ),
    Expanded(
      child: Image.asset('images/pic3.jpg'),
    ),
  ],
);

上面的例子,第二个视图的flex为2 ,显示出来的图就是其他两个的两倍的大小

  • 组合 widgets
    默认情况下,沿其主轴会占用尽可能多的空间,但如果要将子项紧密组合在一起,可以使用 mainAxisSize设置
num MainAxisSize {
	// 根据传入的布局约束,最小化主轴上的可用空间。
	min,
	// 根据传入的布局约束,最大化主轴上的可用空间。
	max,
}

例如将五个星星紧挨在一起,我们就可以使用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),
  ],
)

:布局框架允许你根据需要在行和列内嵌套行和列

通用布局 widgets

Flutter中的 widget 会分为两类:

  • widgets 库 中的标准 widgets : 任何 app 都可以使用 widget 库
  • Material 库 中的widgets: Material库中的组件只能Material app 中使用。
  • widgets 标准库
  • Container:向 widget增加 paddingmarginsbordersbackground color 或者其他的装饰
  • GridView:将 widget 展示为一个可滚动网格
  • ListView:将 widget 展示为一个可滚动列表
  • Stack:将 widget覆盖在另一个的上面。
  • Material
  • Card:将相关信息整理到一个有圆角阴影的盒子中。
  • ListTile:将最多三行的文本、可选的导语以及后面的图标组织在一行中
Container

许多布局都可以随意的用 Container,它可以将使用了padding 或者增加了 borders/marginswidget 分开。
也可以通过将整个布局放到一个 Container 中,并且改变它的背景色或者图片,来改变设备的背景。

  • 增加paddingmarginsborders
  • 改变背景色或者图片
  • 只包含一个子 widget,但是这个子widget 可以是行、列或者是 widget 树的根 widget

更改背景色示例:

Widget _buildImageColumn() => Container(
      decoration: BoxDecoration(
        color: Colors.black26,
      ),
      child: Column(
        children: [
          _buildImageRow(1),
          _buildImageRow(3),
        ],
      ),
    );

添加圆角和外边距示例:

Widget _buildDecoratedImage(int imageIndex) => Expanded(
      child: Container(
        decoration: BoxDecoration(
          border: Border.all(width: 10, color: Colors.black38),
          borderRadius: const BorderRadius.all(const Radius.circular(8)),
        ),
        margin: const EdgeInsets.all(4),
        child: Image.asset('images/pic$imageIndex.jpg'),
      ),
    );
GridView (类似于iOS 中的UICollectionView)
  • 使用 GridViewwidget 作为二维列表展示。类似于iOS中常用的UICollectionView
  • GridView提供两个预制的列表,或者你可以自定义网格。
  • GridView 检测到内容太长而无法适应渲染盒时,它就会自动支持滚动

自定义网格的时候,可以使用

  • GridView.count :允许你制定列的数量
  • GridView.extent:允许你制定单元格的最大宽度

我们看个GridView.extent的使用列子:

// GridView
Widget _buildGridView() => GridView.extent(
  maxCrossAxisExtent: 100,// item最大的宽度
  padding: const EdgeInsets.all(10),// View 距左右屏幕的间隔
  mainAxisSpacing: 10, // item 之间的上下间隔
  crossAxisSpacing: 10,// item 之间的左右间隔
  children: _buildGridTileList(30),
);

// 创建图片列表
// 当对象具有可预测的命名模式时,使用List.generate()构造函数可以轻松创建列表。
List<Container> _buildGridTileList(int count) => List.generate(
    count, (i) => Container(child: Image.asset('assets/pic$i.jpg')));

Flutter探索(二)--- Flutter的布局_第2张图片

ListView
  • ListView,一个和很相似的 widget,当内容长于自己的渲染盒时,就会自动支持滚动.
  • 类似于iOS中的UITableView
  • 一个用来组织盒子中列表的专用 Column(特殊的Column)
  • 可以水平或者垂直布局
  • Column 的配置少,使用更容易,并且支持滚动

使用列子:


// 创建列表
Widget _buildList() => ListView(
  children: [
    _title('List_View_1', 'Hello', Icons.theaters),
    _title('List_View_2', 'Hello', Icons.theaters),
    _title('List_View_3', 'Hello', Icons.theaters),
    _title('List_View_4', 'Hello', Icons.theaters),
    _title('List_View_5', 'Hello', Icons.theaters),
    _title('List_View_6', 'Hello', Icons.theaters),
    _title('List_View_7', 'Hello', Icons.theaters),
    _title('List_View_8', 'Hello', Icons.theaters),
    _title('List_View_9', 'Hello', Icons.theaters),
    _title('List_View_10', 'Hello', Icons.theaters),
    _title('List_View_11', 'Hello', Icons.theaters),
    _title('List_View_12', 'Hello', Icons.theaters),
    _title('List_View_13', 'Hello', Icons.theaters),


  ],
);

// 创建单个的Cell 布局
ListTile _title(String title, String subtitle, IconData icon) => ListTile (
  title: Text(
      title,
      style: TextStyle(
        fontWeight: FontWeight.w500,
        fontSize: 20,
      )),
  subtitle: Text(subtitle),
  leading: Icon(
    icon,
    color: Colors.blue,
  ),
);

Flutter探索(二)--- Flutter的布局_第3张图片

Stack

可以使用 Stack

  • Stack 主要用于一个widget 去覆盖另一个widget
  • 可以完全或者部分覆盖基础 widget
  • 通常 在图片 widget上排列 widget

使用例子:


// Stack Widget
Widget _BuildStackView() => Stack(
  // 设置文字的位置
  alignment: const Alignment(0.6,0.6),
  children: [
    // 圆形图片
    CircleAvatar(
        backgroundImage: AssetImage('assets/pic2.jpg'),
        radius: 100,
    ),
    Container(
      child: Text(
        'Jadekirin',
        style: TextStyle(
          fontSize: 20,
          fontWeight: FontWeight.w500,
          color: Colors.red,
        ),
      ),
    ),
  ],
);

Flutter探索(二)--- Flutter的布局_第4张图片

ListTile
  • ListTileMaterial 库 中专用的行widget
  • 包含最多三行文本以及可选的行前行尾图标的行。
  • ListTileCard 或者ListView 中最常用,但是也可以在别处使用。
  • Row 更少的配置,更容易使用

我看下在上年ListView中使用到的ListTile的例子

// 创建单个的Cell 布局
ListTile _title(String title, String subtitle, IconData icon) => ListTile (
  title: Text(
      title,
      style: TextStyle(
        fontWeight: FontWeight.w500,
        fontSize: 20,
      )),
  subtitle: Text(subtitle),
  leading: Icon(
    icon,
    color: Colors.blue,
  ),
);

在这里插入图片描述

Card
  • Card 来自Material 库中的,几乎可以由任何widget组成,但是通常和 ListTile 一起使用。
  • Card 只有一个子项,这个子项可以是列表网格或者其他支持多个子项的 widget
  • 默认情况下,Card 的大小是 0x0 像素。你可以使用 SizedBox 控制 card 的大小。
  • Card有轻微的圆角阴影来使它具有 3D 效果。改变 Cardelevation 属性可以控制阴影效果
  • Card 的内容无法滚动
// Card 一般结合 SizeBox使用
// SizeBox 控制Card 的大小
Widget _buildCard() => SizedBox(
  height: 240,
  width: 300,
  child: Card(
    child: Column(
      children: [
        // _title('Name', 'Good Bye', Icons.account_circle_rounded),
        // _title('90388283', null, Icons.phone),
        // _title('[email protected]', null, Icons.email),
        ListTile(
          title: Text('1625 Main Street',
              style: TextStyle(fontWeight: FontWeight.w500)),
          subtitle: Text('My City, CA 99984'),
          leading: Icon(
            Icons.account_circle_rounded,
            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('[email protected]'),
          leading: Icon(
            Icons.contact_mail,
            color: Colors.blue[500],
          ),
        ),
      ],
    ),
  ),
);

Flutter探索(二)--- Flutter的布局_第5张图片

你可能感兴趣的:(flutter,Flutter)