在构建任何用户界面时,都离不开文本、图片、图标和按钮这四大基本元素。它们是向用户展示信息、提供视觉引导和接收用户交互的核心。Flutter 提供了功能丰富且易于使用的组件来实现它们。
学习目标
- 掌握
Text
Widget,学会设置字体、颜色、对齐等多种样式。 - 学会使用
Image
Widget 从网络、本地资源和内存中加载图片。 - 掌握
Icon
Widget,并了解如何使用 Flutter 内置的 Material Design 图标库。 - 全面了解 Flutter 中常用的按钮类型,如
ElevatedButton
、TextButton
和IconButton
,并学会如何响应点击事件。
1. Text
:显示文本
Text
Widget 是我们用来在屏幕上显示字符串的组件。它看起来简单,但通过 style
属性,我们可以定制其外观的方方面面。
核心属性
data
: 需要显示的字符串内容。style
(TextStyle ): 用于定义文本样式的对象,这是最重要的属性。fontSize
: 字体大小。color
: 字体颜色。fontWeight
: 字体粗细 (e.g.,FontWeight.bold
加粗)。fontStyle
: 字体样式 (e.g.,FontStyle.italic
斜体)。decoration
: 文本装饰 (e.g.,TextDecoration.underline
下划线)。fontFamily
: 自定义字体(需要先在项目中配置)。
textAlign
: 文本的对齐方式 (e.g.,TextAlign.center
居中)。maxLines
: 文本显示的最大行数。overflow
: 当文本超出maxLines
限制时的处理方式 (e.g.,TextOverflow.ellipsis
显示省略号)。
代码示例:创建一个富文本标签
less
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Text Widget Demo')),
body: const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Hello, Flutter!',
style: TextStyle(
fontSize: 32.0,
color: Colors.blue,
fontWeight: FontWeight.bold,
fontStyle: FontStyle.italic,
decoration: TextDecoration.underline,
decorationColor: Colors.red,
decorationStyle: TextDecorationStyle.wavy,
),
),
SizedBox(height: 20),
Text(
'这是一个很长很长很长很长很长很长很长很长很长很长很长很长很长很长的文本,它会自动换行来适应空间。',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 18),
),
SizedBox(height: 20),
Text(
'这段文字如果太长了就会被截断并显示省略号,因为我们设置了最大行数为1。',
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 18, color: Colors.grey),
),
],
),
),
),
);
}
}
2. Image
:显示图片
Image
Widget 提供了多种构造函数来方便地从不同来源加载图片。
常用构造函数
Image.network()
: 从网络 URL 加载图片。Image.asset()
: 从应用的本地资源文件夹 (assets
) 加载图片。Image.file()
: 从用户手机上的具体文件路径加载图片。Image.memory()
: 从内存中的Uint8List
数据加载图片。
使用本地资源
Image.asset()
的步骤:
在你的项目根目录下创建一个
assets
文件夹 (通常会再建一个子文件夹如assets/images/
)。将图片文件放入该文件夹。
打开项目根目录下的
pubspec.yaml
文件,找到flutter:
部分,取消assets:
的注释,并添加你的资源路径。
yamlflutter: assets: - assets/images/
现在你就可以在代码中使用
Image.asset('assets/images/your_image.png')
了。
核心属性
width
,height
: 图片的宽度和高度。fit
(BoxFit ): 图片的填充方式。BoxFit.cover
: 常用。按比例缩放,裁剪多余部分以完全覆盖容器。BoxFit.contain
: 按比例缩放,完整显示图片,可能会有留白。BoxFit.fill
: 不按比例缩放,拉伸以填满容器,图片可能会变形。BoxFit.fitWidth
/BoxFit.fitHeight
: 按宽度/高度填满,另一边按比例缩放。
代码示例:加载网络和本地图片
less
import 'package:flutter/material.dart';
// 确保你在 pubspec.yaml 中配置了 assets 路径!
// flutter:
// assets:
// - assets/images/
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Image Widget Demo')),
body: SingleChildScrollView( // 使用可滚动视图防止内容溢出
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('从网络加载图片 (Network Image):', style: TextStyle(fontSize: 18)),
Container(
width: 300,
height: 200,
margin: const EdgeInsets.symmetric(vertical: 10),
decoration: BoxDecoration(border: Border.all()),
child: Image.network(
'https://picsum.photos/300/200',
fit: BoxFit.cover,
// 添加加载中的占位符
loadingBuilder: (BuildContext context, Widget child, ImageChunkEvent? loadingProgress) {
if (loadingProgress == null) return child;
return Center(
child: CircularProgressIndicator(
value: loadingProgress.expectedTotalBytes != null
? loadingProgress.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes!
: null,
),
);
},
),
),
const Divider(),
const Text('从本地资源加载图片 (Asset Image):', style: TextStyle(fontSize: 18)),
Container(
width: 150,
height: 150,
margin: const EdgeInsets.symmetric(vertical: 10),
child: Image.asset(
'assets/images/flutter_logo.png', // 假设你的图片放在这个路径
// 如果图片不存在,可以显示一个错误占位符
errorBuilder: (context, error, stackTrace) {
return const Icon(Icons.error, color: Colors.red, size: 50);
},
),
),
],
),
),
),
);
}
}
注意 :你需要自己准备一张名为
flutter_logo.png
的图片并放到assets/images/
目录下才能让本地图片示例正常运行。
3. Icon
:显示图标
Flutter 自带了一套非常丰富的 Material Design 图标,我们可以通过 Icon
Widget 来使用它们。
核心属性
icon_data
: 需要显示的图标,通常来自Icons
类,例如Icons.star
。size
: 图标的大小。color
: 图标的颜色。
dart
Icon(
Icons.favorite, // 图标
color: Colors.pink,
size: 30.0,
semanticLabel: 'Text to announce in accessibility modes', // 辅助功能标签
)
4. Button
:响应用户点击
按钮是应用交互的核心。Flutter 提供了多种设计风格的按钮来满足不同场景的需求。所有按钮都有一个共同的关键属性:onPressed
。
onPressed
: 一个回调函数 (VoidCallback
)。当用户点击按钮时,这个函数会被调用。如果onPressed
被设置为null
,按钮将自动变为禁用状态。
常用按钮类型
a) ElevatedButton (浮起按钮) 这是最常用的按钮类型,有一个背景色和一个轻微的阴影,看起来像是"浮"在界面上。
dart
ElevatedButton(
onPressed: () {
print('ElevatedButton pressed!');
},
child: const Text('Elevated Button'),
)
b) TextButton (文本按钮) 没有背景色和阴影,看起来就像一个可点击的文本标签。通常用于次要操作。
dart
TextButton(
onPressed: () {
print('TextButton pressed!');
},
child: const Text('Text Button'),
)
c) IconButton (图标按钮) 只包含一个图标的按钮,通常用于工具栏或需要节省空间的地方。
dart
IconButton(
icon: const Icon(Icons.thumb_up),
onPressed: () {
print('IconButton pressed!');
},
tooltip: 'Like', // 长按时显示的提示文字
)
d) OutlinedButton (轮廓按钮) 带有一个边框,但没有背景填充色。介于 ElevatedButton
和 TextButton
之间。
dart
OutlinedButton(
onPressed: () {
print('OutlinedButton pressed!');
},
child: const Text('Outlined Button'),
)
完整演示代码
less
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Basic Widgets Demo')),
body: Center(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch, // 让按钮宽度撑满
children: <Widget>[
// Text 和 Icon 结合
const Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.widgets, color: Colors.blue, size: 40),
SizedBox(width: 10),
Text('基础组件', style: TextStyle(fontSize: 28)),
],
),
const Divider(height: 40),
// -- 按钮展示 --
ElevatedButton(
onPressed: () {
print('Elevated Button Clicked');
},
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 12),
),
child: const Text('ElevatedButton', style: TextStyle(fontSize: 18)),
),
const SizedBox(height: 10),
TextButton(
onPressed: () {
print('Text Button Clicked');
},
child: const Text('TextButton', style: TextStyle(fontSize: 18)),
),
const SizedBox(height: 10),
OutlinedButton(
onPressed: () {
print('Outlined Button Clicked');
},
style: OutlinedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 12),
),
child: const Text('OutlinedButton', style: TextStyle(fontSize: 18)),
),
const SizedBox(height: 10),
// IconButton
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
icon: const Icon(Icons.favorite),
iconSize: 30,
color: Colors.red,
onPressed: () {},
),
IconButton(
icon: const Icon(Icons.share),
iconSize: 30,
color: Colors.green,
onPressed: null, // 设置为 null,按钮禁用
),
],
)
],
),
),
),
),
);
}
}
总结
今天我们学习了构建 Flutter 界面的四大基础组件。
Text
用于显示和格式化文本。Image
负责从各种来源加载和显示图片。Icon
提供了丰富的矢量图标库。- 各种
Button
(如ElevatedButton
,TextButton
) 用于响应用户交互。
熟练掌握这些基础组件是构建任何美观且功能丰富的 Flutter 应用的第一步。在下一篇教程中,我们将学习如何处理用户输入,包括文本输入框 (TextField
)、复选框 (Checkbox
) 和开关 (Switch
)。我们下篇见!