Appearance
第5章:Flutter 基础组件
5.1 文本组件(Text)
基本用法
Text 组件是 Flutter 中最常用的组件之一,用于显示文本内容。
基本语法:
dart
Text(
'Hello Flutter',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.blue,
),
textAlign: TextAlign.center,
maxLines: 2,
overflow: TextOverflow.ellipsis,
);常用属性
| 属性 | 描述 | 默认值 |
|---|---|---|
data | 文本内容 | 必填 |
style | 文本样式 | null |
textAlign | 文本对齐方式 | TextAlign.start |
maxLines | 最大行数 | null |
overflow | 文本溢出处理 | TextOverflow.clip |
textDirection | 文本方向 | null |
softWrap | 是否自动换行 | true |
textScaleFactor | 文本缩放因子 | 1.0 |
文本样式(TextStyle)
dart
TextStyle(
fontSize: 16, // 字体大小
fontWeight: FontWeight.w500, // 字体粗细
color: Colors.black, // 字体颜色
fontFamily: 'Roboto', // 字体
fontStyle: FontStyle.italic, // 字体样式
letterSpacing: 1.0, // 字间距
wordSpacing: 2.0, // 词间距
height: 1.5, // 行高
decoration: TextDecoration.underline, // 文本装饰
decorationColor: Colors.red, // 装饰颜色
decorationStyle: TextDecorationStyle.dashed, // 装饰样式
);富文本组件(RichText)
RichText 组件用于显示多种样式的文本:
dart
RichText(
text: TextSpan(
text: 'Hello ',
style: DefaultTextStyle.of(context).style,
children: <TextSpan>[
TextSpan(
text: 'Flutter',
style: const TextStyle(
fontWeight: FontWeight.bold,
color: Colors.blue,
),
),
TextSpan(
text: ' World!',
style: const TextStyle(
fontStyle: FontStyle.italic,
color: Colors.green,
),
),
],
),
);5.2 图片组件(Image)
图片加载方式
Flutter 支持多种图片加载方式:
1. 网络图片
dart
Image.network(
'https://example.com/image.jpg',
width: 200,
height: 200,
fit: BoxFit.cover,
loadingBuilder: (context, child, loadingProgress) {
if (loadingProgress == null) return child;
return const Center(child: CircularProgressIndicator());
},
errorBuilder: (context, error, stackTrace) {
return const Center(child: Icon(Icons.error));
},
);2. 本地图片
首先在 pubspec.yaml 中配置资源:
yaml
flutter:
assets:
- assets/images/然后加载本地图片:
dart
Image.asset(
'assets/images/flutter_logo.png',
width: 100,
height: 100,
);3. 内存图片
dart
Image.memory(
Uint8List.fromList(imageBytes),
width: 200,
height: 200,
);4. 文件图片
dart
Image.file(
File('/path/to/image.jpg'),
width: 200,
height: 200,
);常用属性
| 属性 | 描述 | 默认值 |
|---|---|---|
width | 图片宽度 | null |
height | 图片高度 | null |
fit | 图片缩放方式 | BoxFit.contain |
alignment | 图片对齐方式 | Alignment.center |
repeat | 图片重复方式 | ImageRepeat.noRepeat |
color | 图片颜色滤镜 | null |
colorBlendMode | 颜色混合模式 | null |
图标组件(Icon)
Flutter 内置了大量图标:
dart
Icon(
Icons.home, // 图标名称
size: 24, // 图标大小
color: Colors.blue, // 图标颜色
);常用图标:
Icons.home- 首页Icons.search- 搜索Icons.add- 添加Icons.delete- 删除Icons.settings- 设置Icons.share- 分享Icons.favorite- 收藏Icons.email- 邮件
5.3 按钮组件
ElevatedButton(悬浮按钮,最常用)
dart
ElevatedButton(
onPressed: () {
// 按钮点击事件
print('Button clicked!');
},
onLongPress: () {
// 长按事件
print('Button long pressed!');
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue, // 按钮颜色
foregroundColor: Colors.white, // 文字颜色
elevation: 5, // 阴影
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), // 内边距
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8), // 圆角
),
textStyle: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
child: const Text('Click Me'),
);TextButton(文本按钮)
dart
TextButton(
onPressed: () {
print('Text button clicked!');
},
style: TextButton.styleFrom(
foregroundColor: Colors.blue, // 文字颜色
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
),
child: const Text('Text Button'),
);OutlinedButton(边框按钮)
dart
OutlinedButton(
onPressed: () {
print('Outlined button clicked!');
},
style: OutlinedButton.styleFrom(
foregroundColor: Colors.blue, // 文字颜色
side: const BorderSide(color: Colors.blue), // 边框颜色
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
child: const Text('Outlined Button'),
);图标按钮(IconButton)
dart
IconButton(
onPressed: () {
print('Icon button clicked!');
},
icon: const Icon(Icons.favorite),
iconSize: 24,
color: Colors.red,
tooltip: 'Favorite', // 长按提示
);5.4 输入组件(TextField)
基本用法
dart
TextField(
decoration: InputDecoration(
labelText: 'Username', // 标签文本
hintText: 'Enter your username', // 提示文本
prefixIcon: const Icon(Icons.person), // 前缀图标
suffixIcon: const Icon(Icons.clear), // 后缀图标
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
),
filled: true,
fillColor: Colors.grey[100],
),
keyboardType: TextInputType.text, // 键盘类型
textInputAction: TextInputAction.next, // 键盘操作按钮
autofocus: false, // 是否自动聚焦
obscureText: false, // 是否隐藏文本(密码)
maxLength: 20, // 最大长度
onChanged: (value) {
// 输入变化回调
print('Input: $value');
},
onSubmitted: (value) {
// 提交回调
print('Submitted: $value');
},
);常用属性
| 属性 | 描述 | 默认值 |
|---|---|---|
decoration | 输入框装饰 | null |
controller | 文本控制器 | null |
keyboardType | 键盘类型 | TextInputType.text |
textInputAction | 键盘操作按钮 | TextInputAction.done |
autofocus | 是否自动聚焦 | false |
obscureText | 是否隐藏文本 | false |
maxLength | 最大长度 | null |
maxLines | 最大行数 | 1 |
onChanged | 输入变化回调 | null |
onSubmitted | 提交回调 | null |
enabled | 是否启用 | true |
控制器(TextEditingController)
使用控制器可以更灵活地控制输入框:
dart
final TextEditingController _controller = TextEditingController();
@override
void dispose() {
_controller.dispose();
super.dispose();
}
// 使用
TextField(
controller: _controller,
// ...
);
// 读取值
String value = _controller.text;
// 设置值
_controller.text = 'Hello';
// 清空
_controller.clear();5.5 其他基础组件
Container(容器组件)
Container 是一个多功能的容器组件,可以设置宽高、背景、padding、margin等:
dart
Container(
width: 200,
height: 100,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(8),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
spreadRadius: 2,
blurRadius: 5,
offset: const Offset(0, 2),
),
],
),
padding: const EdgeInsets.all(16),
margin: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
alignment: Alignment.center,
child: const Text('Container', style: TextStyle(color: Colors.white)),
);SizedBox(尺寸盒子)
SizedBox 用于控制组件间距或固定宽高:
dart
// 控制间距
const SizedBox(height: 20);
// 固定宽高
SizedBox(
width: 100,
height: 100,
child: const Text('Fixed size'),
);Card(卡片组件)
Card 组件用于创建带阴影的卡片效果:
dart
Card(
elevation: 5,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
const Text('Card Title', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 8),
const Text('This is a card content'),
],
),
),
);Divider(分割线)
dart
const Divider(
height: 20,
thickness: 2,
color: Colors.grey,
indent: 20,
endIndent: 20,
);SnackBar(提示条)
dart
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const Text('This is a snackbar'),
duration: const Duration(seconds: 3),
action: SnackBarAction(
label: 'Undo',
onPressed: () {
// 撤销操作
},
),
),
);5.6 实操案例:搭建简单登录页面
目标
使用基础组件搭建一个简单的登录页面,包含文本、图片、输入框和按钮。
步骤 1:创建项目
使用 VS Code 或 Android Studio 创建一个新的 Flutter 项目。
步骤 2:创建登录页面
修改 lib/main.dart 文件:
dart
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(
title: 'Login Page',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const LoginPage(),
);
}
}
class LoginPage extends StatefulWidget {
const LoginPage({super.key});
@override
State<LoginPage> createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final TextEditingController _usernameController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
bool _obscurePassword = true;
@override
void dispose() {
_usernameController.dispose();
_passwordController.dispose();
super.dispose();
}
void _login() {
String username = _usernameController.text;
String password = _passwordController.text;
if (username.isEmpty || password.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Please fill in all fields')),
);
return;
}
// 模拟登录
print('Login with $username');
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Login successful')),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[100],
body: SafeArea(
child: Center(
child: SingleChildScrollView(
padding: const EdgeInsets.all(20),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Logo
Container(
width: 100,
height: 100,
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: Colors.blue,
),
child: const Icon(
Icons.lock,
size: 50,
color: Colors.white,
),
),
const SizedBox(height: 40),
// Title
const Text(
'Welcome Back',
style:
TextStyle(fontSize: 28, fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
const Text(
'Sign in to continue',
style: TextStyle(fontSize: 16, color: Colors.grey),
),
const SizedBox(height: 40),
// Username field
TextField(
controller: _usernameController,
decoration: InputDecoration(
labelText: 'Username',
hintText: 'Enter your username',
prefixIcon: const Icon(Icons.person),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
filled: true,
fillColor: Colors.white,
),
),
const SizedBox(height: 20),
// Password field
TextField(
controller: _passwordController,
obscureText: _obscurePassword,
decoration: InputDecoration(
labelText: 'Password',
hintText: 'Enter your password',
prefixIcon: const Icon(Icons.lock),
suffixIcon: IconButton(
icon: Icon(
_obscurePassword
? Icons.visibility
: Icons.visibility_off,
),
onPressed: () {
setState(() {
_obscurePassword = !_obscurePassword;
});
},
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
filled: true,
fillColor: Colors.white,
),
),
const SizedBox(height: 20),
// Forgot password
Align(
alignment: Alignment.centerRight,
child: TextButton(
onPressed: () {
print('Forgot password');
},
child: const Text('Forgot password?'),
),
),
const SizedBox(height: 30),
// Login button
SizedBox(
width: double.infinity,
height: 50,
child: ElevatedButton(
onPressed: _login,
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
textStyle: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
child: const Text('Sign In'),
),
),
const SizedBox(height: 30),
// Register link
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Don\'t have an account?'),
TextButton(
onPressed: () {
print('Register');
},
child: const Text('Sign Up'),
),
],
),
],
),
),
),
),
);
}
}步骤 3:运行应用
- 启动模拟器或连接真机
- 运行项目
- 观察登录页面效果
步骤 4:测试功能
- 尝试输入用户名和密码
- 点击登录按钮,观察提示
- 点击忘记密码链接
- 点击注册链接
- 测试密码显示/隐藏功能
5.7 小结
本章介绍了 Flutter 中常用的基础组件,包括文本组件、图片组件、按钮组件、输入组件以及其他基础组件。这些组件是构建 Flutter 应用界面的基础,掌握它们的使用方法对于 Flutter 开发至关重要。
通过实操案例,我们使用这些基础组件搭建了一个简单的登录页面,体验了组件的组合和交互。在实际开发中,你可以根据需要组合这些组件,创建更加复杂和美观的用户界面。
在接下来的章节中,我们将学习 Flutter 的布局开发,掌握如何使用布局组件来组织和排列这些基础组件,创建更加复杂的页面布局。
