第6讲:常用基础与布局Widget(一):Container, Row, Column
掌握布局三剑客,构建Flutter界面的坚实基础。
你好,欢迎回到《Flutter入门到精通》专栏。在前面的课程中,我们掌握了Widget的核心概念。现在,是时候学习如何使用具体的Widget来搭建用户界面了。本讲将重点介绍三个最基础、最强大的布局Widget:Container、Row和Column。
一、万能的容器:Container
Container
可能是Flutter中最常用、最通用的Widget之一。你可以把它想象成一个万能的盒子,它可以装一个子Widget,并对其进行装饰、定位和约束。
1.1 Container 的基本属性
一个最简单的 Container
可以只包含一个子Widget:
dart
Container(child: Text('Hello, Container!'), )
但它的真正威力在于其丰富的属性:
dart
Container(// 1. 尺寸属性width: 200,height: 100,// constraints: BoxConstraints(maxWidth: 300), // 更复杂的约束// 2. 内边距padding: EdgeInsets.all(16.0), // 所有方向内边距为16// padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10), // 对称内边距// padding: EdgeInsets.only(left: 8, top: 16), // 仅指定某些方向// 3. 外边距margin: EdgeInsets.all(24.0), // 所有方向外边距为24// 4. 装饰 - 这是让Container变漂亮的关键!decoration: BoxDecoration(color: Colors.blue, // 背景色borderRadius: BorderRadius.circular(12.0), // 圆角border: Border.all( // 边框color: Colors.black,width: 2.0,),boxShadow: [ // 阴影BoxShadow(color: Colors.grey.withOpacity(0.5),spreadRadius: 2,blurRadius: 5,offset: Offset(0, 3), // 阴影位置),],),// 5. 对齐方式(当Container有固定尺寸时特别有用)alignment: Alignment.center, // 子Widget在Container内居中// 6. 子Widgetchild: Text('Styled Container',style: TextStyle(color: Colors.white, fontSize: 18),), )
1.2 实际应用示例
让我们创建一个漂亮的卡片式布局:
dart
class CustomCard extends StatelessWidget {const CustomCard({super.key});@overrideWidget build(BuildContext context) {return Container(margin: EdgeInsets.all(16),padding: EdgeInsets.all(20),decoration: BoxDecoration(color: Colors.white,borderRadius: BorderRadius.circular(16),boxShadow: [BoxShadow(color: Colors.grey.withOpacity(0.3),blurRadius: 10,offset: Offset(0, 4),),],),child: Column(mainAxisSize: MainAxisSize.min,crossAxisAlignment: CrossAxisAlignment.start,children: [Text('Flutter开发小贴士',style: TextStyle(fontSize: 20,fontWeight: FontWeight.bold,color: Colors.deepPurple,),),SizedBox(height: 8),Text('Container是一个极其灵活的Widget,可以用于创建卡片、对话框、分隔区域等各种UI元素。',style: TextStyle(fontSize: 14, color: Colors.grey[700]),),],),);} }
二、线性布局:Row 和 Column
Row
和 Column
是用于在水平和垂直方向上排列子Widget的布局Widget,它们共享相似的属性。
2.1 Row - 水平排列
Row
将其子Widget在水平方向(主轴)上排列。
dart
Row(children: <Widget>[Icon(Icons.star, color: Colors.orange),Icon(Icons.star, color: Colors.orange),Icon(Icons.star, color: Colors.orange),Icon(Icons.star_border, color: Colors.grey),Icon(Icons.star_border, color: Colors.grey),SizedBox(width: 8), // 添加间距Text('3.0 (128 reviews)'),], )
Row 的核心属性:
mainAxisAlignment
- 主轴对齐方式(水平方向):MainAxisAlignment.start
:靠左对齐(默认)MainAxisAlignment.end
:靠右对齐MainAxisAlignment.center
:居中对齐MainAxisAlignment.spaceBetween
:子Widget之间平均分布间距MainAxisAlignment.spaceAround
:子Widget周围平均分布间距MainAxisAlignment.spaceEvenly
:子Widget之间和周围都平均分布间距
crossAxisAlignment
- 交叉轴对齐方式(垂直方向):CrossAxisAlignment.start
:顶部对齐CrossAxisAlignment.end
:底部对齐CrossAxisAlignment.center
:垂直居中对齐(默认)CrossAxisAlignment.stretch
:拉伸子Widget以填满交叉轴
示例:不同的对齐方式
dart
Column(children: [// 靠左对齐Row(mainAxisAlignment: MainAxisAlignment.start,children: [Text('Start'), Text('Start')],),// 均匀分布Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,children: [Text('Between'), Text('Between')],),// 垂直方向拉伸Container(color: Colors.grey[200],child: Row(crossAxisAlignment: CrossAxisAlignment.stretch,children: [Container(width: 50, color: Colors.red),Container(width: 50, color: Colors.green),],),),], )
2.2 Column - 垂直排列
Column
将其子Widget在垂直方向(主轴)上排列。
dart
Column(children: <Widget>[Text('商品名称', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),SizedBox(height: 8),Text('这是一个很棒的商品描述,可能会很长...'),SizedBox(height: 16),Text('\$99.99', style: TextStyle(fontSize: 24, color: Colors.red)),SizedBox(height: 16),ElevatedButton(onPressed: () {},child: Text('立即购买'),),], )
Column
的对齐属性与 Row
类似,只是主轴和交叉轴的方向交换了:
mainAxisAlignment
:现在控制垂直方向的对齐crossAxisAlignment
:现在控制水平方向的对齐
2.3 主轴尺寸:mainAxisSize
Row
和 Column
都有一个重要的属性 mainAxisSize
:
MainAxisSize.max
:(默认值)在主轴方向上尽可能大(Row占满可用宽度,Column占满可用高度)MainAxisSize.min
:在主轴方向上尽可能小(只占用子Widget所需的空间)
dart
// 这个Row只会占用其子Widget所需的宽度,而不是整行宽度 Row(mainAxisSize: MainAxisSize.min,children: [Icon(Icons.access_time),SizedBox(width: 4),Text('刚刚'),], )
三、综合实战:构建一个产品卡片
现在,让我们综合运用 Container
、Row
和 Column
来构建一个完整的产品信息卡片。
dart
class ProductCard extends StatelessWidget {const ProductCard({super.key});@overrideWidget build(BuildContext context) {return Container(margin: EdgeInsets.all(16),padding: EdgeInsets.all(16),decoration: BoxDecoration(color: Colors.white,borderRadius: BorderRadius.circular(12),boxShadow: [BoxShadow(color: Colors.grey.withOpacity(0.2),blurRadius: 8,offset: Offset(0, 2),),],),child: Column(crossAxisAlignment: CrossAxisAlignment.start,children: [// 产品标题和价格行Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,children: [Text('无线蓝牙耳机',style: TextStyle(fontSize: 18,fontWeight: FontWeight.bold,),),Text('\$199',style: TextStyle(fontSize: 20,fontWeight: FontWeight.bold,color: Colors.blue,),),],),SizedBox(height: 8),// 评分和销量行Row(children: [// 评分星星Row(children: List.generate(5, (index) => Icon(index < 4 ? Icons.star : Icons.star_border,color: Colors.orange,size: 16,),),),SizedBox(width: 8),Text('4.0', style: TextStyle(fontSize: 14)),SizedBox(width: 16),Text('已售 2.3k', style: TextStyle(fontSize: 14, color: Colors.grey)),],),SizedBox(height: 12),// 产品描述Text('高品质音效,超长续航,舒适佩戴体验,让你的音乐时刻相伴。',style: TextStyle(fontSize: 14, color: Colors.grey[600]),),SizedBox(height: 16),// 按钮行Row(children: [Expanded(child: OutlinedButton(onPressed: () {},child: Text('加入购物车'),),),SizedBox(width: 12),Expanded(child: ElevatedButton(onPressed: () {},child: Text('立即购买'),),),],),],),);} }
代码解析:
外层
Container
:创建卡片的视觉效果(背景色、圆角、阴影)。主
Column
:垂直排列所有内容区块。第一个
Row
:使用spaceBetween
让产品名称和价格分居两侧。第二个
Row
:水平排列评分星星、评分数字和销量信息。第三个
Row
:使用两个Expanded
Widget让两个按钮平均分配可用宽度。
布局技巧与注意事项
使用
SizedBox
添加间距:比Padding
更语义化,专门用于控制尺寸和间距。善用
Expanded
:在Row
或Column
中,让子Widget按比例填充可用空间。处理内容溢出:当内容超出可用空间时,Flutter会显示溢出警告(黄色条纹)。解决方案包括:
使用
SingleChildScrollView
包裹使用
Expanded
或Flexible
调整字体大小或布局
调试布局:在复杂布局中,可以给
Container
临时添加颜色,以便可视化查看每个区域的边界。
结语
恭喜!通过本讲的学习,你已经掌握了Flutter布局系统中最重要的三个基础Widget。Container
、Row
和 Column
的组合使用,可以构建出绝大多数常见的界面布局。
记住这些核心概念:
Container
用于装饰和约束Row
用于水平排列Column
用于垂直排列通过
mainAxisAlignment
和crossAxisAlignment
控制对齐
在下一讲中,我们将继续学习更多强大的布局Widget,包括 Stack
(层叠布局)、Expanded
和 Flexible
等,让你能够应对更复杂的布局挑战。