第6讲:常用基础与布局Widget(一):Container, Row, Column
Text('已售 2.3k', style: TextStyle(fontSize: 14, color: Colors.grey)),Text('商品名称', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),// padding: EdgeInsets.only(left: 8, top: 16), // 仅指定某些方向。
掌握布局三剑客,构建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. 子Widget
child: Text(
'Styled Container',
style: TextStyle(color: Colors.white, fontSize: 18),
),
)
1.2 实际应用示例
让我们创建一个漂亮的卡片式布局:
dart
class CustomCard extends StatelessWidget {
const CustomCard({super.key});
@override
Widget 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});
@override
Widget 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:使用两个ExpandedWidget让两个按钮平均分配可用宽度。
布局技巧与注意事项
-
使用
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 等,让你能够应对更复杂的布局挑战。
更多推荐


所有评论(0)