平台差异处理
Flutter 的一大优势是"一套代码,多端运行",但现实中不同平台往往有不同的设计规范和行为习惯。你需要在代码中识别平台,并做出差异化处理。
判断当前平台
方式一:defaultTargetPlatform(推荐)
dart
import 'package:flutter/foundation.dart';
if (defaultTargetPlatform == TargetPlatform.android) {
// Android 平台逻辑
} else if (defaultTargetPlatform == TargetPlatform.iOS) {
// iOS 平台逻辑
}| 值 | 对应平台 |
|---|---|
TargetPlatform.android | Android |
TargetPlatform.iOS | iOS |
TargetPlatform.macOS | macOS |
TargetPlatform.windows | Windows |
TargetPlatform.linux | Linux |
鸿蒙平台
使用 flutter-ohos 时,鸿蒙平台返回的也是 TargetPlatform.android。如果需要区分 Android 和鸿蒙,需要额外判断。
方式二:dart:io 的 Platform 类
dart
import 'dart:io';
if (Platform.isAndroid) {
// Android
} else if (Platform.isIOS) {
// iOS
}注意
dart:io 的 Platform 类在 Web 平台不可用,调用会抛异常。如果你的项目需要支持 Web,请使用 defaultTargetPlatform 或先用 kIsWeb 做判断。
方式三:kIsWeb(Web 平台专用)
dart
import 'package:flutter/foundation.dart';
if (kIsWeb) {
// Web 平台逻辑
}区分 Android 与鸿蒙
dart
Future<bool> isHarmonyOS() async {
if (defaultTargetPlatform != TargetPlatform.android) {
return false;
}
try {
final channel = const MethodChannel('device_info');
final result = await channel.invokeMethod<String>('getPlatform');
return result == 'ohos';
} on PlatformException {
return false;
}
}条件渲染:根据平台显示不同 UI
基础写法
dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
class PlatformSettingsPage extends StatelessWidget {
const PlatformSettingsPage({super.key});
@override
Widget build(BuildContext context) {
// ─── ★ 根据平台条件渲染 ──────────────
if (defaultTargetPlatform == TargetPlatform.iOS) {
// ─── ★ CupertinoPageScaffold iOS 风格 ──────────────
return CupertinoPageScaffold(
navigationBar: const CupertinoNavigationBar(middle: Text('设置')),
child: SafeArea(
child: Center(child: Text('iOS 风格页面', style: CupertinoTheme.of(context).textTheme.navTitleTextStyle)),
),
);
// ─── ☆ CupertinoPageScaffold iOS 风格 ──────────────
}
// ─── ☆ 根据平台条件渲染 ──────────────
return Scaffold(
appBar: AppBar(title: const Text('设置')),
body: const Center(child: Text('Material 风格页面')),
);
}
}
### 封装 PlatformWidget
```dart
class PlatformWidget extends StatelessWidget {
const PlatformWidget({
super.key,
required this.android,
required this.ios,
this.macOS,
this.windows,
});
final WidgetBuilder android;
final WidgetBuilder ios;
final WidgetBuilder? macOS;
final WidgetBuilder? windows;
@override
Widget build(BuildContext context) {
switch (defaultTargetPlatform) {
case TargetPlatform.iOS:
return ios(context);
case TargetPlatform.macOS:
return macOS?.call(context) ?? ios(context);
case TargetPlatform.windows:
return windows?.call(context) ?? android(context);
default:
return android(context);
}
}
}平台特定的交互适配
页面返回
dart
Widget build(BuildContext context) {
return PopScope(
canPop: true,
onPopInvokedWithResult: (didPop, result) {
if (!didPop) {
// 自定义返回逻辑
}
},
child: Scaffold(...),
);
}滚动物理效果
| 平台 | 默认效果 | Physics |
|---|---|---|
| Android | 到顶/底有光晕效果 | ClampingScrollPhysics |
| iOS | 到顶/底有回弹效果 | BouncingScrollPhysics |
手动指定:
dart
import 'package:flutter/material.dart';
class BouncingListPage extends StatelessWidget {
const BouncingListPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('滚动物理效果')),
body: ListView.builder(
physics: const BouncingScrollPhysics(), // 强制 iOS 风格回弹
itemCount: 30,
itemBuilder: (context, index) => ListTile(title: Text('Item $index')),
),
);
}
}
---
## 平台特定的代码隔离
当不同平台的实现差异很大时,可以利用 Dart 的条件导入:lib/ ├── platform_service.dart # 统一接口 ├── platform_service_stub.dart # Web 空实现 └── platform_service_io.dart # 移动端实现
```dart
// lib/platform_service.dart
export 'platform_service_stub.dart'
if (dart.library.io) 'platform_service_io.dart';
abstract class PlatformService {
String getDeviceInfo();
}这种方式在编译期选择对应平台的实现,不会引入不必要的代码,但语法较复杂,一般在大型项目中使用。对于初学者,简单的 if-else 判断已经足够。
平台差异处理原则
| 原则 | 说明 |
|---|---|
| 默认自适应 | Flutter 的 Scaffold、AppBar 等组件已内置平台适配,优先使用默认行为 |
| 按需判断 | 只在确实需要差异的地方做判断,不要过度使用 |
| 集中管理 | 将平台判断逻辑封装到工具类或组件中,避免到处散落 if-else |
| 充分测试 | 每个平台的差异行为都要在真机或模拟器上验证 |
下一步
- 权限管理 — Android / iOS / 鸿蒙权限配置
