Hola, Amigos! На связи Саша Чаплыгин, Flutter dev компании заказной разработки Amiga. Нашел интересную статью на английском о том, как добавить Flutter в новый или существующий проект Native iOS. Решил поделиться с вами переводом. Это вторая часть, в которой будет идти речь про реализацию экрана Flutter в приложение для iOS и использование platform channel.
Первая часть здесь. Она посвящена созданию приложения на iOS и интеграции Flutter в это приложение.
Третья часть выйдет совсем скоро. Чтобы не пропустить, подписывайтесь на наш телеграм-канал Flutter. Много. Там мы с командой делимся опытом, интересными мероприятиями для разработчиков и другой полезной информацией. В последней статье рассмотрим использование «Hot Reload», «Hot Restart» и тестирование на Codemagic.
Поехали!
Добавление экрана Flutter в приложение iOS
FlutterViewController используется для отображения экрана Flutter внутри приложения iOS. Но также потребуется создать FlutterEngine.
Подходящее место для создания FlutterEngine — внутри AppDelegate.swift
.
Заменяем все содержимое этого файла следующим кодом:
// AppDelegate.swift
import UIKit
import Flutter
import FlutterPluginRegistrant
@UIApplicationMain
class AppDelegate: FlutterAppDelegate {
var flutterEngine : FlutterEngine?;
override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
self.flutterEngine = FlutterEngine(name: "io.flutter", project: nil);
self.flutterEngine?.run(withEntrypoint: nil);
GeneratedPluginRegistrant.register(with: self.flutterEngine!);
return super.application(application, didFinishLaunchingWithOptions: launchOptions);
}
}
Теперь просто добавляем в файл следующие строки ViewController.swift, чтобы отобразить экран на Flutter:
// ViewController.swift
// ...
import Flutter
class ViewController: UIViewController {
// ...
@IBAction func calculatePressed(_ sender: UIButton) {
// ...
let flutterEngine = ((UIApplication.shared.delegate as? AppDelegate)?.flutterEngine)!;
let flutterViewController = FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil);
self.present(flutterViewController, animated: true, completion: nil)
}
}
Если запустим приложение сейчас, то сможем просмотреть экран приложения Flutter Demo Counter, нажав кнопку «CALCULATE» .
Обратитесь к официальной документации Flutter для получения дополнительной информации.
Завершение пользовательского интерфейса Flutter
Пользовательский интерфейс экрана результатов ИМТ будет очень простым и будет содержать всего несколько текстовых виджетов.
Код для пользовательского интерфейса экрана результатов ИМТ:
// main.dart
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'BMI Calculator Module',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
debugShowCheckedModeBanner: false,
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Future<void> _receiveFromHost(MethodCall call) async {
// To be implemented.
// Will be used for retrieving data passed from
// the native iOS app.
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: Colors.blue,
child: Center(
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
'YOUR BMI',
style: TextStyle(
color: Colors.white,
fontSize: 40,
fontWeight: FontWeight.bold),
),
Text(
'23.7',
style: TextStyle(
color: Colors.white,
fontSize: 70,
fontWeight: FontWeight.bold),
),
Text(
'Fit as a fiddle!',
style: TextStyle(
color: Colors.white,
fontSize: 20,
),
),
],
),
),
),
);
}
}
Использование Platform Channel
Используем Platform Channel для передачи данных из приложения iOS в модуль Flutter.
Настройка модуля Flutter (получение данных)
Прежде всего, нужно создать канал с каким-нибудь именем внутри класса
_MyHomePageState
.
// main.dart
static const platform = const MethodChannel('com.souvikbiswas.bmi/data');
Создаем метод
_receiveFromHost()
, который будет извлекать данные, переданные из нативной части, и получим данные для отображения внутри модуля Flutter.
// main.dart
Future<void> _receiveFromHost(MethodCall call) async {
var jData;
try {
print(call.method);
if (call.method == "fromHostToClient") {
final String data = call.arguments;
print(call.arguments);
jData = await jsonDecode(data);
}
} on PlatformException catch (error) {
print(error);
}
setState(() {
jData1 = jData;
if (jData['color'] == 'blue') {
color = Colors.blue;
} else if (jData['color'] == 'green') {
color = Colors.green;
} else {
color = Colors.pink;
}
});
}
Устанавливаем
_receiveFromHost()
метод как Обработчик вызова методаsetMethodCallHandler
.
// main.dart
_MyHomePageState() {
platform.setMethodCallHandler(_receiveFromHost);
}
Пишем код для метода build, чтобы отображать данные, полученные с использованием Platform Channel:
// main.dart
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: color, // Updated
child: Center(
child: Column(
// ...
children: <Widget>[
Text(
'YOUR BMI',
// ...
),
Text(
jData1['value'], // Updated
// ...
),
Text(
jData1['advice'], // Updated
// ...
),
],
),
),
),
);
}
}
Настройка приложения iOS (отправка данных)
Создаем канал для общения с модулем Flutter
// Define inside calculatePressed() method
let bmiDataChannel = FlutterMethodChannel(name: "com.souvikbiswas.bmi/data", binaryMessenger: flutterViewController.binaryMessenger)
Отправляем данные по каналу
// Define inside calculatePressed() method
let bmiDataChannel = FlutterMethodChannel(name: "com.souvikbiswas.bmi/data", binaryMessenger: flutterViewController.binaryMessenger)
let jsonObject: NSMutableDictionary = NSMutableDictionary()
jsonObject.setValue(bmiValue, forKey: "value")
jsonObject.setValue(bmiAdvice, forKey: "advice")
jsonObject.setValue(bmiColor, forKey: "color")
var convertedString: String? = nil
do {
let data1 = try JSONSerialization.data(withJSONObject: jsonObject, options: JSONSerialization.WritingOptions.prettyPrinted)
convertedString = String(data: data1, encoding: String.Encoding.utf8)
} catch let myJSONError {
print(myJSONError)
}
bmiDataChannel.invokeMethod("fromHostToClient", arguments: convertedString)
На этом вторая часть статьи подошла к концу. Мы рассмотрели реализацию экрана Flutter в приложение для iOS и использование platform channel. В последней части речь будет идти про использование «Hot Reload», «Hot Restart» и тестирование на Codemagic.
Чтобы не пропустить анонс, подписывайтесь на наш телеграм-канал Flutter. Много!
Если вы пропустили 1 часть статьи, то она здесь.