🔌 Platform-specific Code
1. Platform Detection
Phần tiêu đề “1. Platform Detection”import 'dart:io';
if (Platform.isAndroid) { // Android code} else if (Platform.isIOS) { // iOS code} else if (Platform.isWindows) { // Windows code} else if (Platform.isMacOS) { // macOS code} else if (Platform.isLinux) { // Linux code}Với kIsWeb
Phần tiêu đề “Với kIsWeb”import 'package:flutter/foundation.dart';
if (kIsWeb) { // Web code} else if (Platform.isAndroid) { // Android code}2. Platform Widgets
Phần tiêu đề “2. Platform Widgets”Cupertino vs Material
Phần tiêu đề “Cupertino vs Material”import 'dart:io';import 'package:flutter/cupertino.dart';import 'package:flutter/material.dart';
Widget buildButton() { if (Platform.isIOS) { return CupertinoButton( onPressed: () {}, child: Text('iOS Button'), ); } else { return ElevatedButton( onPressed: () {}, child: Text('Android Button'), ); }}Platform-aware Widget
Phần tiêu đề “Platform-aware Widget”class PlatformButton extends StatelessWidget { final String text; final VoidCallback onPressed;
const PlatformButton({ super.key, required this.text, required this.onPressed, });
@override Widget build(BuildContext context) { return Platform.isIOS ? CupertinoButton( onPressed: onPressed, child: Text(text), ) : ElevatedButton( onPressed: onPressed, child: Text(text), ); }}3. Platform Channels
Phần tiêu đề “3. Platform Channels”Gọi native code từ Flutter:
Dart side
Phần tiêu đề “Dart side”import 'package:flutter/services.dart';
class BatteryService { static const platform = MethodChannel('com.example.app/battery');
Future<int> getBatteryLevel() async { try { final result = await platform.invokeMethod('getBatteryLevel'); return result as int; } on PlatformException catch (e) { throw Exception('Failed to get battery: ${e.message}'); } }}Android (Kotlin)
Phần tiêu đề “Android (Kotlin)”class MainActivity: FlutterActivity() { private val CHANNEL = "com.example.app/battery"
override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL) .setMethodCallHandler { call, result -> if (call.method == "getBatteryLevel") { val batteryLevel = getBatteryLevel() if (batteryLevel != -1) { result.success(batteryLevel) } else { result.error("UNAVAILABLE", "Battery level not available", null) } } else { result.notImplemented() } } }
private fun getBatteryLevel(): Int { val batteryManager = getSystemService(BATTERY_SERVICE) as BatteryManager return batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) }}iOS (Swift)
Phần tiêu đề “iOS (Swift)”@UIApplicationMainclass AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { let controller = window?.rootViewController as! FlutterViewController let batteryChannel = FlutterMethodChannel( name: "com.example.app/battery", binaryMessenger: controller.binaryMessenger )
batteryChannel.setMethodCallHandler { call, result in if call.method == "getBatteryLevel" { self.receiveBatteryLevel(result: result) } else { result(FlutterMethodNotImplemented) } }
return super.application(application, didFinishLaunchingWithOptions: launchOptions) }
private func receiveBatteryLevel(result: FlutterResult) { let device = UIDevice.current device.isBatteryMonitoringEnabled = true if device.batteryState == UIDevice.BatteryState.unknown { result(FlutterError(code: "UNAVAILABLE", message: "Battery unavailable", details: nil)) } else { result(Int(device.batteryLevel * 100)) } }}4. Conditional Imports
Phần tiêu đề “4. Conditional Imports”abstract class StorageService { Future<void> save(String key, String value); Future<String?> load(String key);}
// storage_mobile.dartimport 'package:shared_preferences/shared_preferences.dart';class StorageServiceImpl implements StorageService { Future<void> save(String key, String value) async { final prefs = await SharedPreferences.getInstance(); await prefs.setString(key, value); } // ...}
// storage_web.dartimport 'dart:html' as html;class StorageServiceImpl implements StorageService { Future<void> save(String key, String value) async { html.window.localStorage[key] = value; } // ...}
// storage.dartexport 'storage_stub.dart' if (dart.library.io) 'storage_mobile.dart' if (dart.library.html) 'storage_web.dart';5. Platform-specific Permissions
Phần tiêu đề “5. Platform-specific Permissions”Android
Phần tiêu đề “Android”<uses-permission android:name="android.permission.CAMERA" /><uses-permission android:name="android.permission.INTERNET" /><!-- ios/Runner/Info.plist --><key>NSCameraUsageDescription</key><string>This app needs camera access</string><key>NSPhotoLibraryUsageDescription</key><string>This app needs photo library access</string>6. Platform-specific UI Patterns
Phần tiêu đề “6. Platform-specific UI Patterns”Back Button
Phần tiêu đề “Back Button”// Android: Hardware back button// iOS: Swipe gesture
// Customize với WillPopScope / PopScopePopScope( canPop: false, onPopInvoked: (didPop) async { if (didPop) return; // Show confirmation }, child: Scaffold(...),)Pull to Refresh
Phần tiêu đề “Pull to Refresh”RefreshIndicator( onRefresh: _refresh, // Material style on Android, Cupertino style configurable child: ListView(...),)7. Theme theo Platform
Phần tiêu đề “7. Theme theo Platform”ThemeData buildTheme() { if (Platform.isIOS) { return ThemeData( // iOS-like styling appBarTheme: AppBarTheme( backgroundColor: Colors.white, foregroundColor: Colors.black, elevation: 0, ), ); } else { return ThemeData( // Material styling useMaterial3: true, ); }}8. Plugin Packages
Phần tiêu đề “8. Plugin Packages”Nhiều packages xử lý platform-specific code cho bạn:
dependencies: # Camera camera: ^0.10.0
# Image picker image_picker: ^1.0.0
# Permissions permission_handler: ^11.0.0
# Local storage shared_preferences: ^2.2.0
# Device info device_info_plus: ^9.0.0
# URL launcher url_launcher: ^6.2.0📝 Tóm tắt
Phần tiêu đề “📝 Tóm tắt”| Approach | Khi nào dùng |
|---|---|
Platform.isX |
Simple platform checks |
| Platform widgets | Different UI per platform |
| Platform channels | Native features không có package |
| Conditional imports | Platform-specific implementations |
| Platform | Native Language |
|---|---|
| Android | Kotlin/Java |
| iOS | Swift/Objective-C |
| Web | JavaScript |
| Desktop | C++/Swift |