Flutter 布局
布局 -- Container
Container widget 可以用来创建一个可见的矩形元素
许多布局都可以随意的用 Container,它可以将使用了 padding 或者增加了 borders/margins 的 widget 分开。可以通过将整个布局放到一个 Container 中,并且改变它的背景色或者图片,来改变设备的背景。
摘要:
(1)、增加 padding、margin、border
(2)、改变背景色或者图片
(3)、只包含一个 widget,可以是行、列、或者是 widget 树的根 widget
常用的属性:
(1)、child:Widget,声明子组件
(2)、padding/margin:EdgeInsets(all(), fromLTRB(), only())
(3)、decoration: BoxDecoration(边框、圆角、渐变、阴影、背景色、背景图片)
(4)、alignment:Alignment,内容对齐
(5)、transform:Matrix4(平移 - translate、旋转 - rotate、缩放 - scale、斜切 - skew)
import 'package:flutter/material.dart'; class Home extends StatelessWidget { const Home({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Container'), ), body: Container( child: const Text( 'Container widget 可以用来创建一个可见的矩形元素。 Container 可以使用 BoxDecoration 来进行装饰,如背景,边框,或阴影等。 Container 还可以设置外边距、内边距和尺寸的约束条件等。另外,Container可以使用矩阵在三维空间进行转换。', style: TextStyle( fontSize: 20, color: Colors.black, decorationStyle: TextDecorationStyle.dotted, ), ), // 宽、高取值可以是一个 double,double.infinity 表示 100% // width: 10.0, // height: 500.0, width: double.infinity, height: double.infinity, padding: const EdgeInsets.all(10.0), margin: const EdgeInsets.fromLTRB(20.0, 20.0, 10.0, 10.0), decoration: BoxDecoration( // 背景颜色 color: Colors.green[300], // 边框样式,可以单独设置四条边,也可以统一设置 // border: const Border( // top: BorderSide( // width: 10.0, // color: Colors.red, // ), // right: BorderSide( // width: 10.0, // color: Colors.green, // ), // bottom: BorderSide( // width: 10.0, // color: Colors.purple, // ), // left: BorderSide( // width: 10.0, // color: Colors.pink, // ), // ), border: Border.all( width: 10.0, color: Colors.blueAccent, ), // 边框圆角,可以单独设置一个角,也可以同时设置四个角 // borderRadius: const BorderRadius.only( // topLeft: Radius.circular(20.0), // ), borderRadius: const BorderRadius.all( Radius.circular(20.0), ), ), ), ); } }
import 'package:flutter/material.dart'; class Home extends StatelessWidget { const Home({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Container'), ), body: Container( child: const Text( 'Container widget 可以用来创建一个可见的矩形元素。 Container 可以使用 BoxDecoration 来进行装饰,如背景,边框,或阴影等。 Container 还可以设置外边距、内边距和尺寸的约束条件等。另外,Container可以使用矩阵在三维空间进行转换。', style: TextStyle( fontSize: 20, // color: Colors.black, ), ), width: 200.0, height: double.infinity, padding: const EdgeInsets.all(10.0), margin: const EdgeInsets.fromLTRB(20.0, 20.0, 10.0, 10.0), decoration: BoxDecoration( border: Border.all( width: 10.0, color: Colors.blueAccent, ), borderRadius: const BorderRadius.all( Radius.circular(20.0), ), color: Colors.green[300], // 设置渐变后,背景色失效 gradient: const LinearGradient( colors: [Colors.lightBlue, Colors.white12], ), ), // 内容的水平、垂直方向对齐方式 alignment: Alignment.center, // 平移 // transform: Matrix4.translationValues(100.0, 0.0, 0.0), // 旋转 // transform: Matrix4.rotationZ(0.1), // 斜切 transform: Matrix4.skewX(0.2), ), ); } }
布局 -- 线性布局
Row 和 Column 这两个 flex widgets 可以让你在水平(Row)和垂直(Column)方向创建灵活的布局。它是基于 web 的 flexbox 布局模型设计的。
Column
Column 中的主轴方向是垂直方向,常用属性:
mainAxisAlignment:MainAxisAlignment 主轴对齐方式
crossAxisAlignment:CrossAxisAlignment 交叉轴对齐方式
children:内容
import 'package:flutter/material.dart'; class Home extends StatelessWidget { const Home({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Column'), elevation: 1.0, centerTitle: true, ), body: Container( child: Column( children: const [ Icon( Icons.access_alarm, size: 50, ), Icon( Icons.ac_unit, size: 50, ), Icon( Icons.access_time, size: 50, ), Icon( Icons.settings, size: 50, ), ], // 主轴的对齐方式 mainAxisAlignment: MainAxisAlignment.spaceEvenly, // 交叉轴的对齐方式 crossAxisAlignment: CrossAxisAlignment.center, ), width: double.infinity, height: double.infinity, margin: const EdgeInsets.all(10.0), padding: const EdgeInsets.all(10.0), decoration: BoxDecoration( border: Border.all( width: 5.0, color: Colors.blue, )), ), ); } }
Row
Row中的主轴方向是水平方向(其它属性与 Column 一致)
import 'package:flutter/material.dart'; class Home extends StatelessWidget { const Home({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Row'), elevation: 1.0, centerTitle: true, ), body: Container( child: Column( // 主轴(垂直方向)的对齐方式 mainAxisAlignment: MainAxisAlignment.start, // 交叉轴(水平方向)的对齐方式 crossAxisAlignment: CrossAxisAlignment.center, children: [ Row( children: const [ Icon( Icons.access_alarm, size: 50, ), Icon( Icons.ac_unit, size: 50, ), Icon( Icons.access_time, size: 50, ), Icon( Icons.settings, size: 50, ), ], // 主轴(水平方向)的对齐方式 mainAxisAlignment: MainAxisAlignment.spaceEvenly, ), ], ), width: double.infinity, height: double.infinity, margin: const EdgeInsets.all(10.0), padding: const EdgeInsets.all(10.0), decoration: BoxDecoration( border: Border.all( width: 5.0, color: Colors.blue, )), ), ); } }
布局 -- 弹性布局
Flex
常用属性:
direction:Axis,声明主轴方向
mainAxisAlignment:MainAxisAlignment,声明主轴对齐方式
textDirection:TextDirection,声明水平方向的排列顺序
crossAxisAlignment:CrossAxisAlignment,声明交叉轴对齐方式
verticalDirection:VerticalDirection,声明垂直方向的排列顺序
children:List<Widget>,声明子组件
import 'package:flutter/material.dart'; class Home extends StatelessWidget { const Home({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Expanded Demo'), ), body: Column(children: <Widget>[ Flex( // 声明主轴方向:水平 或 垂直 direction: Axis.vertical, // 主轴对齐方式 mainAxisAlignment: MainAxisAlignment.spaceAround, textDirection: TextDirection.ltr, children: const [ Icon(Icons.favorite, size: 50), Icon(Icons.audio_file, size: 50), Icon(Icons.beach_access, size: 50), Icon(Icons.security, size: 50), ], ), Flex( direction: Axis.horizontal, children: [ Expanded( flex: 2, // 占比 2/3 child: Container( color: Colors.red, height: 50, ), ), Expanded( flex: 1, // 占比 1/3 child: Container( color: Colors.green, height: 50, ), ) ], ), // 在指定的区域内,指定了flex后,height将失效 Container( height: 100, margin: const EdgeInsets.all(50), child: Flex( direction: Axis.vertical, children: [ // 占比 1/4 Expanded( flex: 1, child: Container( color: Colors.red, height: 90, ), ), // 占比 1/4 const Spacer(), // 占比 2/4 Expanded( flex: 2, child: Container( color: Colors.green, height: 10, ), ), ], ), ), ]), ); } }
Expanded:可伸缩组件
强制子组件(Row、Column、Flex等)填满主轴方向(Row 是水平方向,Column 是垂直方向)的可用空间
常用属性:
flex:int,默认值 1,声明弹性布局所占比例
child:Widget,声明子组件
示例中,没有给 Expanded 指定宽度,但它依然会占满主轴(水平方向)的可用空间,而 Container 则必须指定宽度
import 'package:flutter/material.dart'; class Home extends StatelessWidget { const Home({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Expanded Demo'), ), body: Column(children: <Widget>[ Row( children: <Widget>[ Container( color: Colors.redAccent, // width: 50, // 注意:指定宽度与不指定的区别 width: 50, height: 50, ), ], ), Row( children: <Widget>[ Expanded( child: Container( color: Colors.lightGreen, height: 50, ), ), ], ) ]), ); } }
布局 -- 流式布局
Wrap(解决内容溢出问题)
常用属性:
spacing:主轴方向子组件的间距
alignment:主轴方向的对齐方式
runSpacing:纵轴方向子组件的间距
runAlignment:纵轴方向的对齐方式
Chip(标签)
label: 必填项,通常是一个 Text 组件
avatar:通常是一个 CircleAvatar 组件
CircleAvatar(圆形头像)
backgroundColor:背景颜色
child:组件的内容,通常是一个 Text 组件
import 'package:flutter/material.dart'; class Home extends StatelessWidget { const Home({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Wrap'), ), body: Column( children: [ // 注意:使用Row 和 Wrap 作为容器,容器里面的内容溢出时的处理方式不同 // Row( Wrap( children: const [ Chip( label: Text('喜鹊'), avatar: CircleAvatar( backgroundColor: Colors.blue, child: Text('鸟'), ), ), Chip( label: Text('鹦鹉'), avatar: CircleAvatar( backgroundColor: Colors.blue, child: Text('鸟'), ), ), Chip( label: Text('老鹰'), avatar: CircleAvatar( backgroundColor: Colors.blue, child: Text('鸟'), ), ), Chip( label: Text('鸿雁'), avatar: CircleAvatar( backgroundColor: Colors.blue, child: Text('鸟'), ), ), Chip( label: Text('鸽子'), avatar: CircleAvatar( backgroundColor: Colors.blue, child: Text('鸟'), ), ), Chip( label: Text('麻雀'), avatar: CircleAvatar( backgroundColor: Colors.blue, child: Text('鸟'), ), ), ], ) ], )); } }
import 'package:flutter/material.dart'; class Home extends StatelessWidget { const Home({ Key? key, this.birdList = const ['喜鹊', '鹦鹉', '老鹰', '鸿雁', '鸽子', '麻雀'], this.fishList = const ['福寿鱼', '八宝鱼', '武昌鱼', '鲫鱼', '鲤鱼', '草鱼'], }) : super(key: key); final List<String> birdList; final List<String> fishList; List<Widget> _getBird() { return birdList .map( (item) => Chip( label: Text(item), avatar: const CircleAvatar( backgroundColor: Colors.blue, child: Text('鸟'), ), ), ) .toList(); } List<Widget> _getFish() { return fishList .map( (item) => Chip( label: Text(item), avatar: const CircleAvatar( backgroundColor: Colors.purple, child: Text('鱼'), ), ), ) .toList(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Wrap'), ), body: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Wrap( children: _getBird(), spacing: 18.0, // 水平方向的间距 alignment: WrapAlignment.spaceAround, // 主轴方向的对齐方式 runSpacing: 100.0, // 垂直方向的间距 ), Wrap( children: _getFish(), ), ], ), ); } }
布局 -- Card
Card(卡片) 是一个带有圆角和阴影效果的面板,通常用于展示一些相关联的信息,如相册、地理位置、联系信息等
属性:
child:Widget,子组件
color:Color,背景色
shadowColor:Color,背景色
elevation:double,阴影高度
shape:ShapeBorder,边框样式
margin:外边距
ListTile:列表瓦片
leading:Widget,子头部组件
title:Widget,子标题
subtitle:Widget,子标题
import 'package:flutter/material.dart'; class Home extends StatelessWidget { const Home({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Container'), ), body: Column( children: [ Card( child: Column( children: const [ ListTile( leading: Icon( Icons.supervised_user_circle_rounded, size: 50, ), title: Text( '张三', style: TextStyle( fontSize: 30, ), ), subtitle: Text( '总经理', style: TextStyle( fontSize: 20, ), ), ), Divider(), ListTile( title: Text( '电话:18623450987', style: TextStyle(fontSize: 20), ), ), ListTile( title: Text( '地址:北京市长安街特一号', style: TextStyle(fontSize: 20), ), ), ], ), ), Card( margin: const EdgeInsets.all(30), color: Colors.purpleAccent[100], shadowColor: Colors.yellow, // 阴影颜色 elevation: 20, // 阴影高度 // 边框样式 shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(40), side: const BorderSide( color: Colors.yellow, width: 3.0, ), ), child: Column( children: const [ ListTile( leading: Icon( Icons.supervised_user_circle_rounded, size: 50, ), title: Text( '李四', style: TextStyle( fontSize: 30, ), ), subtitle: Text( '董事长', style: TextStyle( fontSize: 20, ), ), ), Divider(), ListTile( title: Text( '电话:13289072376', style: TextStyle(fontSize: 20), ), ), ListTile( title: Text( '地址:吉林省吉林市发展大道1号', style: TextStyle(fontSize: 20), ), ), ], ), ), ], ), ); } }