Text
在 Flutter 中,Text 组件是负责显示文本的核心部件,几乎出现在任何需要展示文字的地方。它非常灵活,既可以显示简单的单一样式文本,也能通过 Text.rich 构建复杂的富文本效果。
1. 核心用法与基本参数
使用 Text 最基本的方式就是创建一个 Text 实例,并传入要显示的字符串。但通过设置不同的参数,可以控制其布局和截断方式。
-
textAlign(文本对齐) :控制文本在Text组件内的水平对齐方式,例如TextAlign.center(居中)、TextAlign.left(左对齐)。需要注意的是,只有当Text组件的宽度大于文本实际内容宽度时,对齐设置才会生效。 -
maxLines(最大行数) :限制文本最多显示的行数。默认情况下,文本会自动换行。设置此参数后,超出部分的行将不会被显示-1。 -
overflow(溢出处理) :当文本内容超出maxLines限制或父容器约束时,如何处理溢出。常用的有:TextOverflow.ellipsis:用省略号“...”表示被截断的文本。TextOverflow.clip:直接裁剪掉溢出的文本(默认行为)。TextOverflow.fade:将溢出的文本边缘渐隐处理。
-
softWrap(是否软换行) :决定文本是否在换行符处自动换行。如果设为false,文本将只占一行,可能导致水平方向溢出。 -
textScaleFactor(文本缩放因子) :一个快速放大或缩小文本的因子。例如,设为1.5会使所有文本放大50%。不过,官方现在更推荐使用textScaler来获得更精细的控制。
示例:
import 'package:flutter/material.dart';
void main(List<String> args) {
runApp(MainPage());
}
class MainPage extends StatelessWidget {
const MainPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("Text组件"),
),
body: Container(
// 文本居中方式
alignment: Alignment.center,
width: double.infinity,
height: double.infinity,
color: Colors.amber,
child: Text.rich(TextSpan(
text: "Hello",
children: [
TextSpan(
text: "Flutter",style: TextStyle(color: Colors.green)
),
TextSpan(text:"!")
],
style: TextStyle(
// 字体颜色
color: Colors.red,
// 字体大小
fontSize: 40,
// 字重
fontWeight: FontWeight.bold
)
)),
// 当字体显示数量超过对应行数时,其余文本将进行隐藏,并截断文本用...显示。
// child: Text("今天天气很冷,今天天气很冷,今天天气很冷,今天天气很冷,今天天气很冷,今天天气很冷,今天天气很冷,今天天气很冷,今天天气很冷,今天天气很冷,今天天气很冷,今天天气很冷,",
// style: TextStyle(
// color: Colors.blue,
// fontSize: 30
// ),
// maxLines: 2,
// // 溢出隐藏
// overflow: TextOverflow.ellipsis,
// ),
// 基础Text组件
// child:Text("Hello Flutter!",style: TextStyle(
// fontSize: 30,
// color: Colors.blue,
// fontStyle: FontStyle.italic,
// fontWeight: FontWeight.w600,
// decoration: TextDecoration.underline,
// decorationColor: Colors.red
// ),),
)
),
);
}
}
2. 样式定制 (TextStyle)
Text 组件的样式主要通过 style 属性来设置,其值是一个 TextStyle 对象。TextStyle 提供了极其丰富的参数来定义文本的外观-5-10。
-
基础样式:如
color(颜色)、fontSize(字号)、fontWeight(字重,如粗体)、fontStyle(样式,如斜体)。 -
间距与行高:
letterSpacing和wordSpacing控制字符和单词的间距。height用于设置行高,它的值是fontSize的倍数。例如height: 1.5且fontSize: 20.0,则最终行高为 30.0 逻辑像素。
-
装饰效果:
decoration:添加下划线 (TextDecoration.underline)、删除线 (TextDecoration.lineThrough) 等。decorationColor和decorationStyle分别设置装饰的颜色和样式(如虚线、波浪线)。
-
高级效果:通过
background和foreground属性,可以使用Paint对象实现更复杂的效果,比如给文本添加背景色,或使用渐变色、描边等。
示例:
Text(
'Hello World',
style: TextStyle(
// 字体大小
fontSize: 24.0,
// 字体颜色
color: Colors.blue,
fontWeight: FontWeight.bold,
// 装饰央视
decoration: TextDecoration.underline,
// 字体颜色
decorationColor: Colors.red,
// 字符
decorationStyle: TextDecorationStyle.wavy,
// 字符间距
letterSpacing: 2.0,
),
)
3. 富文本 (TextSpan 与 Text.rich)
如果一段文本中需要包含多种样式(例如一句话里部分文字是蓝色且可点击),就不能使用普通的 Text 了。这时需要用到 TextSpan 和 Text.rich 构造函数。
TextSpan 代表一个具有独立样式的文本“片段”。多个 TextSpan 可以组合在一起,形成复杂的富文本结构。
text:显示的文本。style:显示文本的样式。children:一个TextSpan列表,用于嵌套更多的片段。recognizer:为这个片段添加手势识别,比如点击事件。
示例:
以下代码创建了一个带有可点击链接的富文本。
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
Text.rich(
TextSpan(
text: '访问 ',
children: <TextSpan>[
TextSpan(
text: 'Flutter 官网',
style: const TextStyle(color: Colors.blue),
recognizer: TapGestureRecognizer()
..onTap = () {
// 处理点击事件,例如打开网页
print('链接被点击了');
},
),
TextSpan(text: ' 了解更多。'),
],
),
)
4. 全局样式管理 (DefaultTextStyle)
在一个页面的多个地方使用相同的文本样式时,如果每个 Text 都单独设置 style,代码会显得冗余。Flutter 提供了 DefaultTextStyle 组件来管理全局或局部的默认文本样式。
DefaultTextStyle 可以包裹一个组件子树,并为其设置默认的 style 和 textAlign。该子树中所有未显式指定样式的 Text 组件,都会自动继承这个默认样式。
示例:
dart
复制下载
// 默认文本样式
DefaultTextStyle(
style: const TextStyle(
color: Colors.red,
fontSize: 20.0,
),
// 文本居中方式
textAlign: TextAlign.center,
child: Column(
children: const [
Text('这段文字是红色的20号字并居中'), // 继承样式
Text('我也是同样的样式'),
Text(
'但我有不同样式',
style: TextStyle( // 局部覆盖
inherit: false, // 可选择不继承默认样式
color: Colors.grey,
),
),
],
),
)
通过设置 inherit: false,子 Text 可以选择完全不继承父级的默认样式。
5. 使用自定义字体
要在应用中使用自定义字体(如非系统默认的字体文件),需要完成两个步骤:
-
在
pubspec.yaml中声明:将字体文件(通常放在fonts或assets目录下)的路径和样式在配置文件中声明。flutter: fonts: - family: MyCustomFont # 字体的家族名称 fonts: - asset: fonts/MyCustomFont-Regular.ttf - asset: fonts/MyCustomFont-Bold.ttf weight: 700 # 指定该文件对应的字重 -
在
TextStyle中使用:通过fontFamily属性引用你在pubspec.yaml中定义的字体家族名称。Text( '这是自定义字体', style: TextStyle( fontFamily: 'MyCustomFont', fontSize: 30.0, ), )
Image
在 Flutter 中,Image 组件是用于显示图片的核心部件。它能够从不同的来源加载图片,并提供丰富的参数来控制图片的显示尺寸、缩放模式、颜色混合等效果。
下面我们来详细解析 Image 组件的图片来源、核心参数、缓存机制以及常见问题。
1. 图片的来源
Flutter 提供了多种构造函数,用于从不同的数据源加载图片:
| 构造函数 | 描述 | 使用场景 |
|---|---|---|
Image.asset | 从应用程序的资源(pubspec.yaml 中声明的文件)中加载图片。 | 加载应用内置的图标、背景图、本地静态图片。 |
Image.network | 从网络 URL 加载图片。 | 加载用户头像、商品图片等来自服务器的动态图片。 |
Image.file | 从本地文件系统中加载图片(需要相应的权限)。 | 加载用户从相册选择的图片,或应用下载到本地的图片。 |
Image.memory | 从内存中的 Uint8List 数据加载图片。 | 加载动态生成的图片,或已经从网络/文件读取到内存中的图片数据。 |
Image | 通用构造函数,需要配合 ImageProvider 使用。 | 当你需要自定义 ImageProvider 时使用。 |
示例:
import 'package:flutter/material.dart';
void main(List<String> args) {
runApp(MainPage());
}
class MainPage extends StatelessWidget {
const MainPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("Text组件"),
),
body: Container(
alignment: Alignment.center,
width: double.infinity,
height: double.infinity,
decoration: BoxDecoration(color: Colors.amber),
// 从应用程序中加载资源
child: Image.asset("lib/images/github.jpg",
width: 100,
height: 100,
fit: BoxFit.cover,
// fit:BoxFit.contain
// fit:BoxFit.fill,
),
)
,
),
);
}
}
import 'package:flutter/material.dart';
void main(List<String> args) {
runApp(MainPage());
}
class MainPage extends StatelessWidget {
const MainPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("Text组件"),
),
body: Container(
alignment: Alignment.center,
width: double.infinity,
height: double.infinity,
decoration: BoxDecoration(color: Colors.amber),
// 从网络中加载图片资源
child: Image.network("https://vmmp.qpic.cn/vmedia/xh/mulpic/mzc00200m2a6lpy_1280_720_1771402161898/0?imageView2/2/w/700",
width: 400,
height: 300,
fit: BoxFit.cover,
),
)
,
),
);
}
}
2. 核心参数与用法
Image 组件提供了丰富的参数来精确控制图片的显示效果。
2.1 控制尺寸
-
width&height:显式设置图片的宽度和高度。如果不设置,Image会尝试根据父容器约束和图片原始尺寸来决定自己的大小。 -
boxFit:这是最重要的参数之一,用于指定图片的缩放模式,决定图片如何适应Image组件分配到的空间。它接收一个BoxFit枚举值:BoxFit.contain:保持图片原始宽高比,使图片完整地显示在组件内。可能导致组件区域留有空白。BoxFit.cover:保持图片原始宽高比,使图片完全覆盖组件区域。图片可能会被裁剪。BoxFit.fill:不保持宽高比,拉伸图片以填满组件区域。图片可能会失真。BoxFit.fitWidth:保持宽高比,将图片的宽度拉伸至与组件宽度一致,高度自动调整。BoxFit.fitHeight:保持宽高比,将图片的高度拉伸至与组件高度一致,宽度自动调整。BoxFit.scaleDown:类似于contain,但如果图片原始尺寸小于组件,则不会放大图片。
2.2 对齐与重复
alignment:当图片尺寸小于组件,或者因为fit设置导致留有空白时,alignment决定图片在组件内的对齐方式。例如Alignment.center、Alignment.topLeft。repeat:如果图片尺寸小于组件,是否允许图片在水平和垂直方向上重复平铺。通常用于背景纹理。
2.3 颜色混合
color&colorBlendMode:这两个属性结合使用,可以为图片叠加一层颜色。color指定要叠加的颜色,colorBlendMode指定混合模式(如BlendMode.multiply、BlendMode.srcIn)。这对于创建遮罩、改变图片色调或实现占位图效果非常有用。
示例:
Image.network(
'https://example.com/avatar.jpg',
width: 100,
height: 100,
fit: BoxFit.cover, // 覆盖整个100x100区域,可能会裁剪
alignment: Alignment.center,
color: Colors.blue.withOpacity(0.3),
colorBlendMode: BlendMode.multiply,
)
3. 图片缓存与性能
对于网络图片,Flutter 的 Image.network 默认会使用缓存。但其缓存机制是内存缓存,而不是磁盘缓存。这意味着图片在应用重启后会丢失,需要重新下载。
为了更好地控制缓存策略,尤其是对网络图片进行磁盘缓存,通常会使用 cached_network_image 这个第三方库。
使用 cached_network_image:
- 在
pubspec.yaml中添加依赖。 - 使用
CachedNetworkImage组件。
CachedNetworkImage(
imageUrl: 'https://example.com/large_image.jpg',
placeholder: (context, url) => const CircularProgressIndicator(), // 加载中的占位组件
errorWidget: (context, url, error) => const Icon(Icons.error), // 加载失败的占位组件
fit: BoxFit.cover,
)
这个库会将图片缓存到本地磁盘,并管理内存缓存,大大提升了图片加载的效率和用户体验。
4. 圆角与形状
要在 Flutter 中实现图片圆角或圆形头像,通常有两种方法:
方法一:使用 ClipRRect 或 CircleAvatar
将 Image 组件包裹在一个裁剪组件中。
-
ClipRRect:用于实现圆角矩形。ClipRRect( borderRadius: BorderRadius.circular(10.0), child: Image.network('https://p26-passport.byteacctimg.com/img/user-avatar/9447af82b1e48e41744bce604ab6ef1f~100x100.awebp'), ) -
CircleAvatar:专门用于实现圆形头像。CircleAvatar( backgroundImage: NetworkImage('https://p26-passport.byteacctimg.com/img/user-avatar/9447af82b1e48e41744bce604ab6ef1f~100x100.awebp'), radius: 30, )
方法二:使用 Container 的 decoration
这是更灵活、更常用的方法。将 Image 作为 Container 的背景图,并设置圆角。
Container(
width: 100,
height: 100,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15.0),
image: const DecorationImage(
image: NetworkImage('https://p26-passport.byteacctimg.com/img/user-avatar/9447af82b1e48e41744bce604ab6ef1f~100x100.awebp'),
fit: BoxFit.cover,
),
),
)
这种方法的好处是可以在 BoxDecoration 中同时设置边框、阴影、渐变和背景图片。
5. 常见问题与最佳实践
-
问题:图片变形
- 原因:通常是因为没有正确使用
fit属性,或者直接设置了width和height但没有指定fit,导致图片被拉伸以适应给定的尺寸。 - 解决:根据需要选择合适的
BoxFit模式(如cover、contain)。
- 原因:通常是因为没有正确使用
-
问题:本地图片不显示
-
原因:几乎总是因为
pubspec.yaml文件配置错误,比如路径缩进不正确、文件路径写错或资源文件未包含在assets列表中。 -
解决:仔细检查
pubspec.yaml的格式。确保assets:部分位于flutter:下,并且路径缩进正确(通常为两个空格)。flutter: assets: - assets/images/ # 包含整个目录 - assets/icons/logo.png # 包含单个文件
-
-
最佳实践:为网络图片指定占位图
-
为了避免在图片加载完成前出现空白区域,使用
FadeInImage或cached_network_image库来显示加载中的占位图,提供更平滑的用户体验。
// 使用 FadeInImage (Flutter 内置) FadeInImage.assetNetwork( placeholder: 'assets/placeholder.png', // 本地占位图 image: 'https://p26-passport.byteacctimg.com/img/user-avatar/9447af82b1e48e41744bce604ab6ef1f~100x100.awebp', fit: BoxFit.cover, ) -