diff --git a/example/ios/Runner/AppDelegate.swift b/example/ios/Runner/AppDelegate.swift index 70693e4..2ac4143 100644 --- a/example/ios/Runner/AppDelegate.swift +++ b/example/ios/Runner/AppDelegate.swift @@ -1,13 +1,18 @@ import UIKit import Flutter - +import presentation_displays @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { + SwiftPresentationDisplaysPlugin.controllerAdded = controllerAdded GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } + func controllerAdded(controller:FlutterViewController) + { + GeneratedPluginRegistrant.register(with: controller) + } } diff --git a/example/lib/main.dart b/example/lib/main.dart index fa71ffe..9c3bebd 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -46,7 +46,7 @@ class Button extends StatelessWidget { onPressed: function, child: Text( title, - style: TextStyle(fontSize: 40), + style: TextStyle(fontSize: 25), ), ), ); @@ -63,6 +63,14 @@ class _DisplayManagerScreenState extends State { DisplayManager displayManager = DisplayManager(); List displays = []; + TextEditingController _indexToShareController = TextEditingController(); + TextEditingController _dataToTransferController = TextEditingController(); + + TextEditingController _nameOfIdController = TextEditingController(); + String _nameOfId = ""; + TextEditingController _nameOfIndexController = TextEditingController(); + String _nameOfIndex = ""; + @override Widget build(BuildContext context) { return Scaffold( @@ -70,47 +78,179 @@ class _DisplayManagerScreenState extends State { title: const Text('Plugin example app'), ), body: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Wrap( - alignment: WrapAlignment.center, - children: [ - Button("Get Displays", () async { - final values = await displayManager.getDisplays(); - print(values); - displays.clear(); - displays.addAll(values!); - print(displays); - }), - Button("Show presentation", () async { - displayManager.showSecondaryDisplay( - displayId: displays.length > 0 - ? displays[1]?.displayId ?? -1 - : -1, - routerName: "presentation"); - }), - Button("NameByDisplayId", () async { - final value = await displayManager - .getNameByDisplayId(displays[1]?.displayId ?? -1); - print(value); - }), - Button("NameByIndex", () async { - final value = await displayManager.getNameByIndex(1); - print(value); - }), - Button("TransferData", () async { - final value = await displayManager - .transferDataToPresentation("test transfer data"); - print(value); - }) - ], - ), - ], + child: SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + _getDisplays(), + _showPresentation(), + _transferData(), + _getDisplayeById(), + _getDisplayByIndex(), + ], + ), ), ), ); } + + Widget _getDisplays() { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Button("Get Displays", () async { + final values = await displayManager.getDisplays(); + print(values); + displays.clear(); + + setState(() { + displays.addAll(values!); + }); + print(displays); + }), + ListView.builder( + scrollDirection: Axis.vertical, + shrinkWrap: true, + padding: const EdgeInsets.all(8), + itemCount: displays.length, + itemBuilder: (BuildContext context, int index) { + return Container( + height: 50, + child: Center( + child: Text( + ' ${displays[index]?.displayId} ${displays[index]?.name}')), + ); + }), + Divider() + ], + ); + } + + Widget _showPresentation() { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: TextField( + controller: _indexToShareController, + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Index to share screen', + ), + ), + ), + Button("Show presentation", () async { + int? index = int.tryParse(_indexToShareController.text); + if (index != null && index < displays.length) { + displayManager.showSecondaryDisplay( + displayId: + displays.length > 0 ? displays[index]?.displayId ?? -1 : 1, + routerName: "presentation"); + } + }), + Divider(), + ], + ); + } + + Widget _transferData() { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: TextField( + controller: _dataToTransferController, + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Data to transfer', + ), + ), + ), + Button("TransferData", () async { + String data = _dataToTransferController.text; + + final value = await displayManager.transferDataToPresentation(data); + print(value); + }), + Divider(), + ], + ); + } + + Widget _getDisplayeById() { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: TextField( + controller: _nameOfIdController, + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Id', + ), + ), + ), + Button("NameByDisplayId", () async { + int? id = int.tryParse(_nameOfIdController.text); + if (id != null) { + final value = await displayManager + .getNameByDisplayId(displays[id]?.displayId ?? -1); + print(value); + setState(() { + _nameOfId = value ?? ""; + }); + } + }), + Container( + height: 50, + child: Center(child: Text(_nameOfId)), + ), + Divider(), + ], + ); + } + + Widget _getDisplayByIndex() { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: TextField( + controller: _nameOfIndexController, + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'Index', + ), + ), + ), + Button("NameByIndex", () async { + int? index = int.tryParse(_nameOfIndexController.text); + if (index != null) { + final value = await displayManager.getNameByIndex(index); + print(value); + setState(() { + _nameOfIndex = value ?? ""; + }); + } + }), + Container( + height: 50, + child: Center(child: Text(_nameOfIndex)), + ), + Divider(), + ], + ); + } } /// UI of Presentation display diff --git a/ios/Classes/SwiftPresentationDisplaysPlugin.swift b/ios/Classes/SwiftPresentationDisplaysPlugin.swift index 08b0766..7c23107 100644 --- a/ios/Classes/SwiftPresentationDisplaysPlugin.swift +++ b/ios/Classes/SwiftPresentationDisplaysPlugin.swift @@ -2,45 +2,128 @@ import Flutter import UIKit public class SwiftPresentationDisplaysPlugin: NSObject, FlutterPlugin { - static var additionalWindows = [UIWindow]() - var flutterEngineChannel:FlutterMethodChannel=FlutterMethodChannel() + var additionalWindows = [UIScreen:UIWindow]() + var screens = [UIScreen]() + var flutterEngineChannel:FlutterMethodChannel=FlutterMethodChannel() + public static var controllerAdded: ((FlutterViewController)->Void)? - public static func register(with registrar: FlutterPluginRegistrar) { - let channel = FlutterMethodChannel(name: "presentation_displays_plugin", binaryMessenger: registrar.messenger()) - let instance = SwiftPresentationDisplaysPlugin() - registrar.addMethodCallDelegate(instance, channel: channel) - - NotificationCenter.default.addObserver(forName: UIScreen.didConnectNotification, - object: nil, queue: nil) { notification in + public override init() { + super.init() + + screens.append(UIScreen.main) + NotificationCenter.default.addObserver(forName: UIScreen.didConnectNotification, + object: nil, queue: nil) { + notification in + // Get the new screen information. let newScreen = notification.object as! UIScreen + let screenDimensions = newScreen.bounds - + print(newScreen.description) + for s in self.screens { + print("here: "+s.description) + } // Configure a window for the screen. let newWindow = UIWindow(frame: screenDimensions) newWindow.screen = newScreen - + // You must show the window explicitly. - newWindow.isHidden = false + newWindow.isHidden = true + // Save a reference to the window in a local array. - self.additionalWindows.append(newWindow) - } - } - - public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { - // result("iOS " + UIDevice.current.systemVersion) - if call.method=="showPresentation"{ - showPresentation() - } - else if call.method=="transferDataToPresentation"{ - self.flutterEngineChannel.invokeMethod("DataTransfer", arguments: call.arguments) - } - } - private func showPresentation() - { - let extVC = FlutterViewController() - extVC.setInitialRoute("presentation") - SwiftPresentationDisplaysPlugin.additionalWindows[0].rootViewController = extVC - self.flutterEngineChannel = FlutterMethodChannel(name: "presentation_displays_plugin_engine", binaryMessenger: extVC.binaryMessenger) + self.screens.append(newScreen) + self.additionalWindows[newScreen]=newWindow + + } + + NotificationCenter.default.addObserver(forName: + UIScreen.didDisconnectNotification, + object: nil, + queue: nil) { notification in + let screen = notification.object as! UIScreen + + // Remove the window associated with the screen. + for s in self.screens { + if s == screen { + + let index = self.screens.index(of: s) + self.screens.remove(at: index!) + // Remove the window and its contents. + self.additionalWindows.removeValue(forKey: s) + } + } + } + } + + public static func register(with registrar: FlutterPluginRegistrar) { + let channel = FlutterMethodChannel(name: "presentation_displays_plugin", binaryMessenger: registrar.messenger()) + let instance = SwiftPresentationDisplaysPlugin() + registrar.addMethodCallDelegate(instance, channel: channel) + + } + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + // result("iOS " + UIDevice.current.systemVersion) + if call.method=="listDisplay" + { + var jsonDisplaysList:String = "["; + let screensList = self.screens + for i in 0.. + { + print(json) + showPresentation(index:json["displayId"] as? Int ?? 1, routerName: json["routerName"] as? String ?? "presentation") + } + else { + print("bad json") + } + } + catch let error as NSError { + print(error) + } + } + else if call.method=="transferDataToPresentation"{ + self.flutterEngineChannel.invokeMethod("DataTransfer", arguments: call.arguments) + } + else + { + result(FlutterMethodNotImplemented) + } + + } + + private func showPresentation(index:Int, routerName:String ) + { + if index>0 && index < self.screens.count && self.additionalWindows.keys.contains(self.screens[index]) + { + let screen=self.screens[index] + let window=self.additionalWindows[screen] + + // You must show the window explicitly. + window?.isHidden=false + + let extVC = FlutterViewController() + SwiftPresentationDisplaysPlugin.controllerAdded!(extVC) + extVC.setInitialRoute(routerName) + window?.rootViewController = extVC + + + self.flutterEngineChannel = FlutterMethodChannel(name: "presentation_displays_plugin_engine", binaryMessenger: extVC.binaryMessenger) + } + + } + } -} diff --git a/pubspec.yaml b/pubspec.yaml index 43ec08f..b1f1e4e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,12 +1,12 @@ name: presentation_displays description: Flutter plugin supports to run on two screens. It's basically a tablet connected to another screen via an HDMI or Wireless homepage: https://github.com/VNAPNIC/presentation-displays -version: 0.1.9 +version: 0.1.10 author: vn.apnic@gmail.com environment: - sdk: ">=2.12.0 <3.0.0" - flutter: ">=1.12.0 <2.0.0" + sdk: '>=2.12.0 <3.0.0' + flutter: '>=1.12.0 <2.0.0' dependencies: flutter: @@ -24,4 +24,4 @@ flutter: package: com.namit.presentation_displays pluginClass: PresentationDisplaysPlugin ios: - pluginClass: PresentationDisplaysPlugin \ No newline at end of file + pluginClass: PresentationDisplaysPlugin