Flutter 基础组件实战:Text 与 Container 组件快速上手
·
一、引言
基础的Text和Container组件是 Flutter 界面开发的 “基石”,但仅掌握基础用法不足以应对实际开发中的复杂场景。本文在基础用法之上,补充进阶属性、多场景实战案例、常见问题解决方案,所有代码均可直接复制运行,帮助你从 “会用” 到 “活用” 这两个核心组件。
二、Text 组件:从基础样式到进阶定制
2.1 基础属性回顾(补充易忽略细节)
import 'package:flutter/material.dart';
void main() {
runApp(const TextBasicEnhanceApp());
}
class TextBasicEnhanceApp extends StatelessWidget {
const TextBasicEnhanceApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text("Text进阶基础")),
body: const Padding(
padding: EdgeInsets.all(16),
child: Text(
"Flutter跨平台开发\n一行代码多端运行",
style: TextStyle(
fontSize: 18,
color: Colors.black87,
fontWeight: FontWeight.w600, // 更精细的字体粗细(w100-w900)
fontStyle: FontStyle.normal,
letterSpacing: 1.2, // 字间距(字符之间的距离)
wordSpacing: 3.0, // 词间距(英文单词之间的距离,中文无效果)
height: 1.5, // 行高(相对于字体大小的倍数,如1.5倍行高)
textBaseline: TextBaseline.alphabetic, // 文本基线(对齐方式)
),
textAlign: TextAlign.justify, // 两端对齐(需文本足够长才生效)
textDirection: TextDirection.ltr, // 文本方向(ltr从左到右,rtl从右到左)
softWrap: true, // 自动换行(默认true,设为false则强制单行)
overflow: TextOverflow.fade, // 溢出渐变隐藏(替代ellipsis)
textScaleFactor: 1.1, // 文本缩放比例(适配系统字体大小)
),
),
),
);
}
}
关键补充说明:
letterSpacing/wordSpacing:优化文本排版,提升可读性(尤其英文 / 数字);height:行高是 “倍数” 而非固定值,比如fontSize:18 + height:1.5→ 实际行高 = 27;textScaleFactor:适配系统字体大小设置(用户在手机设置中调大 / 调小字体时,文本自动缩放);overflow的更多取值:TextOverflow.ellipsis:省略号;TextOverflow.fade:溢出部分渐变透明;TextOverflow.clip:直接裁剪(无提示,慎用)。
2.2 进阶:富文本(RichText)实现多样式文本
普通Text只能设置单一样式,RichText可实现 “一段文本多种样式”(如关键词标红、混合字体),是实际开发中高频用法:
dart
import 'package:flutter/material.dart';
void main() {
runApp(const RichTextDemoApp());
}
class RichTextDemoApp extends StatelessWidget {
const RichTextDemoApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text("富文本实战")),
body: const Padding(
padding: EdgeInsets.all(16),
child: RichText(
text: TextSpan(
// 基础样式(所有子TextSpan默认继承)
style: TextStyle(
fontSize: 16,
color: Colors.black87,
height: 1.4,
),
children: [
TextSpan(text: "用户协议:"),
// 协议链接(蓝色+下划线)
TextSpan(
text: "《Flutter使用条款》",
style: TextStyle(
color: Color(0xFF2196F3),
decoration: TextDecoration.underline,
),
// 可添加点击事件(后续结合GestureDetector)
),
TextSpan(text: "和"),
// 隐私政策(红色+加粗)
TextSpan(
text: "《隐私保护指引》",
style: TextStyle(
color: Colors.red,
fontWeight: FontWeight.bold,
),
),
TextSpan(text: ",您需同意后才能继续使用。"),
],
),
),
),
),
);
}
}
拓展:富文本 + 点击事件
给富文本中的 “链接” 添加点击跳转,只需嵌套GestureDetector:
dart
// 替换上面的RichText外层
GestureDetector(
onTap: () {
// 点击《Flutter使用条款》的逻辑(如跳转到网页)
debugPrint("点击了使用条款");
},
child: const RichText(/* 原有富文本内容 */),
)
三、Container 组件:从基础容器到布局神器
3.1 进阶属性补充(margin/transform/constraints)
dart
import 'package:flutter/material.dart';
void main() {
runApp(const ContainerAdvanceApp());
}
class ContainerAdvanceApp extends StatelessWidget {
const ContainerAdvanceApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text("Container进阶")),
body: Padding(
padding: const EdgeInsets.all(20),
child: Container(
// 1. 外边距(容器与外部组件的距离)
margin: const EdgeInsets.only(bottom: 20),
// 2. 对齐方式(子组件在容器内的位置)
alignment: Alignment.bottomRight,
// 3. 约束(强制宽高范围,优先级高于width/height)
constraints: const BoxConstraints(
minWidth: 200, // 最小宽度
maxWidth: 300, // 最大宽度
minHeight: 100, // 最小高度
maxHeight: 150, // 最大高度
),
// 4. 变换(旋转/缩放/平移,不影响布局)
transform: Matrix4.rotationZ(0.05), // 顺时针旋转5度(弧度制)
transformAlignment: Alignment.center, // 旋转中心
// 5. 装饰(新增“形状”和“图片背景”)
decoration: BoxDecoration(
color: Colors.grey[100],
// 形状(圆形/矩形,与borderRadius二选一)
// shape: BoxShape.circle, // 圆形(需宽高相等)
borderRadius: BorderRadius.circular(8),
// 图片背景(替代渐变/纯色)
// image: const DecorationImage(
// image: NetworkImage("https://xxx.png"), // 网络图片
// fit: BoxFit.cover, // 图片填充方式
// ),
border: Border(
// 单边边框(替代全边框)
left: BorderSide(color: Colors.blue, width: 4),
bottom: BorderSide(color: Colors.blue, width: 2),
),
),
child: const Text(
"进阶Container",
style: TextStyle(fontSize: 18),
),
),
),
),
);
}
}
核心补充说明:
marginvspadding:margin:容器 “外部” 间距(与父组件 / 其他组件的距离);padding:容器 “内部” 间距(与子组件的距离);
constraints:约束宽高范围,适配不同屏幕(比如设置maxWidth: 300,在小屏手机上自动缩窄);transform:变换仅改变视觉效果,不影响布局(比如旋转后,容器占位大小不变);DecorationImage:支持本地 / 网络图片作为背景,搭配fit属性(cover/contain/fill等)控制填充方式。
3.2 实战:Container 实现 “自适应布局”
实际开发中常需 “宽度适配屏幕,高度随内容变化”,代码如下:
dart
import 'package:flutter/material.dart';
void main() {
runApp(const ContainerAutoLayoutApp());
}
class ContainerAutoLayoutApp extends StatelessWidget {
const ContainerAutoLayoutApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text("自适应Container")),
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Container(
width: double.infinity, // 宽度占满父组件(自适应屏幕)
// 不设置height,高度随子组件内容自动变化
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
boxShadow: const [BoxShadow(color: Colors.black12, blurRadius: 4)],
),
padding: const EdgeInsets.all(16),
child: const Column(
crossAxisAlignment: CrossAxisAlignment.start, // 子组件左对齐
mainAxisSize: MainAxisSize.min, // Column高度随内容收缩
children: [
Text(
"自适应标题",
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
SizedBox(height: 8),
Text(
"这是一段自适应高度的文本,内容越多,Container的高度会自动增加,宽度则占满整个屏幕(左右留边距)。实际开发中,这种布局常用于“消息卡片”“商品介绍”等场景。",
style: TextStyle(fontSize: 16, color: Colors.black54),
),
],
),
),
),
),
);
}
}
四、高频实战组合案例(直接复用)
4.1 案例 1:列表式卡片(Text+Container+ListTile)
实现 APP 中常见的 “消息列表 / 联系人列表” 布局:
dart
import 'package:flutter/material.dart';
void main() {
runApp(const ListCardDemoApp());
}
class ListCardDemoApp extends StatelessWidget {
const ListCardDemoApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text("列表卡片实战")),
body: ListView(
// 列表可滚动
children: [
_buildListCard(
icon: Icons.notifications,
title: "系统通知",
subTitle: "您的账号已完成实名认证",
time: "10:00",
),
_buildListCard(
icon: Icons.shopping_cart,
title: "订单提醒",
subTitle: "您的订单已发货,预计明天送达",
time: "09:30",
),
_buildListCard(
icon: Icons.message,
title: "新消息",
subTitle: "客服:您的问题已处理完成",
time: "08:15",
),
],
),
),
);
}
// 封装列表卡片组件
Widget _buildListCard({
required IconData icon,
required String title,
required String subTitle,
required String time,
}) {
return Container(
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
boxShadow: const [BoxShadow(color: Colors.black12, blurRadius: 2)],
),
child: Row(
children: [
// 左侧图标
Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: Colors.blue[100],
borderRadius: BorderRadius.circular(20),
),
child: Icon(icon, color: Colors.blue, size: 20),
),
const SizedBox(width: 12),
// 中间文本区域(自适应宽度)
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
),
const SizedBox(height: 4),
Text(
subTitle,
style: const TextStyle(fontSize: 14, color: Colors.black54),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
],
),
),
// 右侧时间
Text(
time,
style: const TextStyle(fontSize: 12, color: Colors.black45),
),
],
),
);
}
}
4.2 案例 2:按钮式 Container(替代原生 Button)
自定义样式按钮(比原生ElevatedButton更灵活):
dart
import 'package:flutter/material.dart';
void main() {
runApp(const CustomButtonApp());
}
class CustomButtonApp extends StatelessWidget {
const CustomButtonApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text("自定义按钮")),
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// 主按钮
GestureDetector(
onTap: () => debugPrint("点击主按钮"),
child: Container(
width: double.infinity,
height: 50,
alignment: Alignment.center,
decoration: BoxDecoration(
color: const Color(0xFF2196F3),
borderRadius: BorderRadius.circular(25),
boxShadow: const [
BoxShadow(color: Color(0xFF2196F3).withOpacity(0.3), blurRadius: 8)
],
),
child: const Text(
"确认提交",
style: TextStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.w600),
),
),
),
const SizedBox(height: 16),
// 次要按钮(边框式)
GestureDetector(
onTap: () => debugPrint("点击次要按钮"),
child: Container(
width: double.infinity,
height: 50,
alignment: Alignment.center,
decoration: BoxDecoration(
border: Border.all(color: const Color(0xFF2196F3), width: 1),
borderRadius: BorderRadius.circular(25),
),
child: const Text(
"取消操作",
style: TextStyle(color: Color(0xFF2196F3), fontSize: 18, fontWeight: FontWeight.w600),
),
),
),
],
),
),
),
);
}
}
五、常见问题与解决方案(避坑指南)
5.1 Text 组件常见问题
| 问题现象 | 原因 | 解决方案 |
|---|---|---|
| 文本换行异常 | softWrap: false 或父组件宽度不足 |
1. 设softWrap: true;2. 给父组件设置合理宽度 / 用Expanded自适应 |
| 富文本点击事件不生效 | 直接给TextSpan加onTap(需 Material 环境) |
1. 确保外层是MaterialApp;2. 嵌套GestureDetector包裹RichText |
| 文本缩放后排版错乱 | textScaleFactor 缩放导致行高 / 间距异常 |
结合MediaQuery限制缩放范围:textScaleFactor: min(MediaQuery.of(context).textScaleFactor, 1.2) |
5.2 Container 组件常见问题
| 问题现象 | 原因 | 解决方案 |
|---|---|---|
decoration和color同时使用报错 |
两者互斥,decoration中已包含color |
删掉color,将颜色移到decoration: BoxDecoration(color: ...)中 |
| Container 设置宽高不生效 | 父组件有constraints约束(如ListView/Row) |
1. 用ConstrainedBox包裹;2. 给Container加constraints属性 |
| 渐变背景不显示 | 渐变颜色值相同,或begin/end方向错误 |
1. 确保渐变颜色不同;2. 调整begin/end(如Alignment.top→Alignment.bottom) |
| 阴影不显示 | boxShadow的color透明度太高,或blurRadius为 0 |
1. 降低透明度(如Colors.black12→Colors.black26);2. 设置blurRadius > 0 |
六、总结与拓展
- Text 组件:基础样式靠
TextStyle,多样式文本用RichText,溢出处理优先选ellipsis/fade,适配系统字体用textScaleFactor; - Container 组件:核心是
decoration(背景 / 边框 / 阴影)、constraints(宽高约束)、margin/padding(间距),变换用transform(不影响布局); - 组合思路:
- 简单文本卡片:
Container + Text; - 列表项:
Container + Row + Icon + Text; - 自定义按钮:
Container + GestureDetector + Text;
- 简单文本卡片:
- 拓展学习:后续可结合
Row/Column/Stack实现复杂布局,结合StatefulWidget给组件添加交互逻辑。
欢迎大家加入[开源鸿蒙跨平台开发者社区](https://openharmonycrossplatform.csdn.net),一起共建开源鸿蒙跨平台生态。
更多推荐



所有评论(0)