Flutter Cupertino 组件详解
Cupertino 组件是 Flutter 提供的 iOS 风格 UI 组件库,让你的应用在 iOS 设备上拥有原生 iOS 的外观和交互体验。
一、核心组件概览
1. 应用结构组件
dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyCupertinoApp());
}
class MyCupertinoApp extends StatelessWidget {
const MyCupertinoApp({super.key});
@override
Widget build(BuildContext context) {
return const CupertinoApp(
title: 'iOS风格应用',
theme: CupertinoThemeData(
brightness: Brightness.light,
primaryColor: CupertinoColors.activeBlue,
),
home: CupertinoHomePage(),
);
}
}
2. 页面骨架与导航
dart
class CupertinoHomePage extends StatelessWidget {
const CupertinoHomePage({super.key});
@override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: const Text('首页'),
trailing: CupertinoButton(
padding: EdgeInsets.zero,
child: const Icon(CupertinoIcons.add),
onPressed: () {},
),
),
child: SafeArea(
child: ListView(
children: [
// 页面内容
],
),
),
);
}
}
二、常用 Cupertino 组件详解
1. 导航相关组件
CupertinoNavigationBar
dart
CupertinoNavigationBar(
// 左侧按钮
leading: CupertinoButton(
padding: EdgeInsets.zero,
child: const Text('返回'),
onPressed: () => Navigator.pop(context),
),
// 中间标题
middle: const Text('设置'),
// 右侧按钮
trailing: CupertinoButton(
padding: EdgeInsets.zero,
child: const Icon(CupertinoIcons.gear),
onPressed: () {},
),
// 边框设置
border: const Border(bottom: BorderSide(color: CupertinoColors.systemGrey2)),
// 是否半透明
backgroundColor: CupertinoColors.systemBackground.withOpacity(0.9),
)
CupertinoSliverNavigationBar(可滚动导航栏)
dart
CustomScrollView(
slivers: [
CupertinoSliverNavigationBar(
largeTitle: const Text('大型标题'),
trailing: CupertinoButton(
child: const Icon(CupertinoIcons.ellipsis_circle),
onPressed: () {},
),
),
// 其他 Sliver 组件
],
)
2. 底部标签栏
dart
class CupertinoTabbedApp extends StatelessWidget {
const CupertinoTabbedApp({super.key});
@override
Widget build(BuildContext context) {
return CupertinoTabScaffold(
tabBar: CupertinoTabBar(
items: const [
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.home),
label: '首页',
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.search),
label: '搜索',
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.person),
label: '我的',
),
],
activeColor: CupertinoColors.activeBlue,
inactiveColor: CupertinoColors.systemGrey,
backgroundColor: CupertinoColors.systemBackground,
),
tabBuilder: (context, index) {
// 返回对应的页面
switch (index) {
case 0:
return const HomePage();
case 1:
return const SearchPage();
case 2:
return const ProfilePage();
default:
return Container();
}
},
);
}
}
3. 按钮组件
CupertinoButton
dart
// 填充按钮
CupertinoButton.filled(
onPressed: () {},
child: const Text('填充按钮'),
)
// 边框按钮
CupertinoButton(
onPressed: () {},
color: CupertinoColors.activeBlue,
borderRadius: BorderRadius.circular(8),
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
child: const Text('普通按钮'),
)
// 无边框文本按钮
CupertinoButton(
onPressed: () {},
child: const Text('文本按钮'),
padding: EdgeInsets.zero, // 去掉默认内边距
)
// 禁用状态
CupertinoButton(
onPressed: null, // null 表示禁用
child: const Text('禁用按钮'),
)
CupertinoContextMenu
dart
CupertinoContextMenu(
actions: [
CupertinoContextMenuAction(
child: const Text('分享'),
onPressed: () {},
trailingIcon: CupertinoIcons.share,
),
CupertinoContextMenuAction(
child: const Text('删除'),
onPressed: () {},
isDestructiveAction: true, // 危险操作
),
],
child: Container(
width: 100,
height: 100,
color: CupertinoColors.systemGrey5,
child: const Center(child: Text('长按显示菜单')),
),
)
4. 输入控件
CupertinoTextField
dart
CupertinoTextField(
controller: TextEditingController(),
placeholder: '请输入内容',
prefix: const Icon(CupertinoIcons.search),
suffix: CupertinoButton(
padding: EdgeInsets.zero,
child: const Icon(CupertinoIcons.clear_thick_circled),
onPressed: () {},
),
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
style: CupertinoTheme.of(context).textTheme.textStyle,
decoration: BoxDecoration(
border: Border.all(color: CupertinoColors.systemGrey3),
borderRadius: BorderRadius.circular(8),
),
obscureText: true, // 密码模式
keyboardType: TextInputType.emailAddress,
)
CupertinoSearchTextField(搜索框)
dart
CupertinoSearchTextField(
onChanged: (value) {
// 搜索逻辑
},
onSubmitted: (value) {
// 提交搜索
},
placeholder: '搜索...',
prefixIcon: const Icon(CupertinoIcons.search),
suffixIcon: const Icon(CupertinoIcons.mic),
style: CupertinoTheme.of(context).textTheme.textStyle,
)
5. 选择器
CupertinoPicker
dart
// 滚动选择器
int selectedIndex = 0;
CupertinoPicker(
scrollController: FixedExtentScrollController(initialItem: selectedIndex),
itemExtent: 32,
onSelectedItemChanged: (index) {
setState(() {
selectedIndex = index;
});
},
children: List.generate(10, (index) => Center(
child: Text('选项 $index'),
)),
)
// 日期选择器
DateTime selectedDate = DateTime.now();
CupertinoDatePicker(
mode: CupertinoDatePickerMode.dateAndTime,
initialDateTime: selectedDate,
minimumDate: DateTime(2000),
maximumDate: DateTime(2100),
onDateTimeChanged: (DateTime newDate) {
setState(() {
selectedDate = newDate;
});
},
use24hFormat: true,
)
// 时间选择器
Duration selectedDuration = const Duration(hours: 1);
CupertinoTimerPicker(
mode: CupertinoTimerPickerMode.hm,
minuteInterval: 5,
onTimerDurationChanged: (Duration newDuration) {
setState(() {
selectedDuration = newDuration;
});
},
)
6. 对话框与提示
CupertinoAlertDialog
dart
showCupertinoDialog(
context: context,
builder: (context) => CupertinoAlertDialog(
title: const Text('确认'),
content: const Text('确定要删除吗?'),
actions: [
CupertinoDialogAction(
child: const Text('取消'),
onPressed: () => Navigator.pop(context),
isDefaultAction: true,
),
CupertinoDialogAction(
child: const Text('删除'),
onPressed: () {
// 删除操作
Navigator.pop(context);
},
isDestructiveAction: true,
),
],
),
)
CupertinoActionSheet(操作表)
dart
showCupertinoModalPopup(
context: context,
builder: (context) => CupertinoActionSheet(
title: const Text('选择操作'),
message: const Text('请选择一个操作'),
actions: [
CupertinoActionSheetAction(
onPressed: () {
Navigator.pop(context, '拍照');
},
child: const Text('拍照'),
),
CupertinoActionSheetAction(
onPressed: () {
Navigator.pop(context, '从相册选择');
},
child: const Text('从相册选择'),
),
],
cancelButton: CupertinoActionSheetAction(
onPressed: () => Navigator.pop(context),
isDefaultAction: true,
child: const Text('取消'),
),
),
)
CupertinoActivityIndicator
dart
// 小型加载指示器
const CupertinoActivityIndicator(radius: 10)
// 大型加载指示器
const CupertinoActivityIndicator.partiallyRevealed(
progress: 0.5, // 进度 0-1
radius: 15,
animating: true,
)
7. 开关、滑块和分段控件
CupertinoSwitch
dart
bool switchValue = false;
CupertinoSwitch(
value: switchValue,
onChanged: (value) {
setState(() {
switchValue = value;
});
},
activeColor: CupertinoColors.activeGreen,
trackColor: CupertinoColors.systemGrey,
)
CupertinoSlider
dart
double sliderValue = 0.5;
CupertinoSlider(
value: sliderValue,
min: 0,
max: 1,
divisions: 10,
onChanged: (value) {
setState(() {
sliderValue = value;
});
},
activeColor: CupertinoColors.activeBlue,
thumbColor: CupertinoColors.white,
)
CupertinoSegmentedControl
dart
int segmentedValue = 0;
CupertinoSegmentedControl<int>(
groupValue: segmentedValue,
onValueChanged: (value) {
setState(() {
segmentedValue = value;
});
},
children: const {
0: Text('全部'),
1: Text('进行中'),
2: Text('已完成'),
},
selectedColor: CupertinoColors.activeBlue,
unselectedColor: CupertinoColors.systemBackground,
borderColor: CupertinoColors.systemGrey3,
pressedColor: CupertinoColors.systemGrey5,
)
8. 列表和单元格
CupertinoListTile
dart
CupertinoListTile(
leading: Icon(CupertinoIcons.person, color: CupertinoColors.systemGrey),
title: const Text('个人资料'),
subtitle: const Text('查看和编辑个人资料'),
trailing: const CupertinoListTileChevron(),
onTap: () {
// 导航到个人资料页面
},
)
// 带开关的列表项
CupertinoListTile(
title: const Text('消息通知'),
trailing: CupertinoSwitch(
value: notificationEnabled,
onChanged: (value) {
setState(() {
notificationEnabled = value;
});
},
),
)
CupertinoListSection
dart
CupertinoListSection.insetGrouped(
header: const Text('设置'),
children: [
CupertinoListTile.notched(
title: const Text('账号设置'),
onTap: () {},
),
CupertinoListTile.notched(
title: const Text('隐私设置'),
onTap: () {},
),
CupertinoListTile.notched(
title: const Text('通用设置'),
onTap: () {},
),
],
)
9. 特殊界面组件
CupertinoSlidingSegmentedControl(滑动分段控件)
dart
int slidingValue = 0;
CupertinoSlidingSegmentedControl<int>(
groupValue: slidingValue,
onValueChanged: (value) {
setState(() {
slidingValue = value!;
});
},
children: const {
0: Text('Tab 1'),
1: Text('Tab 2'),
2: Text('Tab 3'),
},
)
CupertinoScrollbar(iOS风格滚动条)
dart
CupertinoScrollbar(
controller: scrollController,
child: ListView.builder(
controller: scrollController,
itemCount: 100,
itemBuilder: (context, index) {
return ListTile(title: Text('Item $index'));
},
),
)
三、实用技巧和最佳实践
1. 混合使用 Material 和 Cupertino
dart
// 根据平台自动选择组件
Theme.of(context).platform == TargetPlatform.iOS
? CupertinoButton(...)
: ElevatedButton(...);
// 或使用 Platform.isIOS 判断
import 'dart:io';
Platform.isIOS
? CupertinoNavigationBar(...)
: AppBar(...);
2. 自定义 Cupertino 主题
dart
CupertinoApp(
theme: CupertinoThemeData(
brightness: Brightness.light,
primaryColor: CupertinoColors.systemBlue,
primaryContrastingColor: CupertinoColors.white,
textTheme: CupertinoTextThemeData(
textStyle: const TextStyle(fontFamily: 'SF Pro'),
navTitleTextStyle: TextStyle(
fontSize: 17,
fontWeight: FontWeight.w600,
color: CupertinoColors.label,
),
),
barBackgroundColor: CupertinoColors.systemBackground,
scaffoldBackgroundColor: CupertinoColors.systemGroupedBackground,
),
)
3. 完整的 iOS 风格应用示例
dart
class IOSMessengerApp extends StatelessWidget {
const IOSMessengerApp({super.key});
@override
Widget build(BuildContext context) {
return CupertinoApp(
theme: const CupertinoThemeData(
brightness: Brightness.light,
),
home: CupertinoTabScaffold(
tabBar: CupertinoTabBar(
items: const [
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.bubble_left_bubble_right),
label: '聊天',
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.phone),
label: '通话',
),
],
),
tabBuilder: (context, index) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text(index == 0 ? '聊天' : '通话'),
trailing: CupertinoButton(
padding: EdgeInsets.zero,
child: const Icon(CupertinoIcons.pencil),
onPressed: () {},
),
),
child: ListView.builder(
itemCount: 20,
itemBuilder: (context, index) {
return CupertinoListTile(
leading: Container(
width: 50,
height: 50,
decoration: BoxDecoration(
color: CupertinoColors.systemGrey5,
borderRadius: BorderRadius.circular(25),
),
child: const Icon(CupertinoIcons.person_fill),
),
title: Text('联系人 $index'),
subtitle: const Text('最后一条消息...'),
trailing: const Text('刚刚'),
onTap: () {
showCupertinoDialog(
context: context,
builder: (context) => CupertinoAlertDialog(
title: const Text('开始聊天'),
content: Text('确定要联系联系人 $index 吗?'),
actions: [
CupertinoDialogAction(
child: const Text('取消'),
onPressed: () => Navigator.pop(context),
),
CupertinoDialogAction(
child: const Text('确定'),
onPressed: () => Navigator.pop(context),
),
],
),
);
},
);
},
),
);
},
),
);
}
}
四、注意事项
- 平台适配:Cupertino 组件主要用于 iOS 平台,在 Android 上使用会显得不协调
- 性能考虑:大量使用动画效果时注意性能优化
- 用户体验:遵循 iOS 设计规范,保持原生交互习惯
- 图标使用 :优先使用
CupertinoIcons中的图标 - 状态管理:Cupertino 组件与 Material 组件一样,可以使用各种状态管理方案
五、资源推荐
- 官方文档:https://api.flutter.dev/flutter/cupertino/cupertino-library.html
- Human Interface Guidelines:https://developer.apple.com/design/human-interface-guidelines/
- SF Symbols:https://developer.apple.com/sf-symbols/(iOS 原生图标)
通过掌握这些 Cupertino 组件,你可以为 iOS 用户提供原生的、符合 iOS 设计规范的优秀应用体验!