[英]How to add a FlutterViewController to a UIViewController
[英]How can I “push” a UIViewController from FlutterViewController
我想在我們的 Flutter 視圖上“推送”一個新的原生視圖(Android 中的 Activity 和 iOS 中的 UIViewController),在新的原生視圖完成/完成后,讓屏幕回到我們的 Flutter 視圖。
我可以在 Android 中做到這一點。 但是我對 iOS 很陌生,當我嘗試在ios/Runner/AppDelegate.m
執行此操作時:
SwiftViewController *swiftViewController = [controller.storyboard instantiateViewControllerWithIdentifier:@"SwiftViewController"];
[(FlutterViewController *)self.window.rootViewController pushViewController:swiftViewController animated:YES];
它給出了錯誤:
“FlutterViewController”沒有可見的@interface 聲明了選擇器“pushViewController:animated”
那么如何在iOS中做到這一點呢? 謝謝
在 Swift 中,我們可以使用方法通道從顫動動作事件中打開原生 iOS viewController,
var platform = const MethodChannel('com.nativeActivity/iosChannel');
final String result = await platform.invokeMethod('StartNativeIOS');
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let methodChannel = FlutterMethodChannel(name: "com.nativeActivity/iosChannel", binaryMessenger:controller.binaryMessenger)
methodChannel.setMethodCallHandler({
(call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
if call.method == "StartNativeIOS" {
let mainVC = MainViewController() // Your viewController
let navigationController = UINavigationController(rootViewController: mainVC)
self.window.rootViewController = navigationController
self.window.makeKeyAndVisible()
} else {
result(FlutterMethodNotImplemented)
return
}
})
它會起作用! 歡呼
注意:但是沒有回到顫振視圖。
所以這是正確的方法。 使用協調器模式的顫振導航
pushViewController
僅在您的控制器是navigation stack
的一部分時才有效,即如果您的FlutterViewController
嵌入在UINavigationController
,那么您可以像這樣從它push
另一個控制器:
self.navigationController?.pushViewController(swiftViewController, animated: true)
第二個選項是:如果FlutterViewController
未嵌入UINavigationController
,您可以簡單地從它present
另一個控制器,如下所示:
self.present(swiftViewController, animated: true, completion: nil)
您需要以編程方式或在故事板中將 FlutterViewController 嵌入容器UINavigationController中,然后您將能夠推送您的下一個控制器。
以下是如何以編程方式嵌入的示例:
@interface AppDelegate()
@property (nonatomic, strong) UINavigationController *navigationController;
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GeneratedPluginRegistrant registerWithRegistry:self];
UIViewController *flutterViewController = [[FlutterViewController alloc] init];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:flutterViewController];
[self.navigationController setNavigationBarHidden:YES];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
return true;
}
- (void)pushExample {
UIViewController *viewController = [[UIViewController alloc] init];
[self.navigationController pushViewController:viewController animated:true];
}
@end
需要時(例如點擊按鈕)調用pushExample
。 您也可以在此視頻中查看“故事板”方式
也許你可以看看webview插件。 與您的描述類似,它們啟動了一個新的 Activity 或 UIViewController。 顯然,您不需要啟動網絡視圖。
帶有按鈕的小部件。 點擊按鈕應該推送依賴消息以將視圖控制器推送到 iOS 應用程序。
class BodyWidget extends StatelessWidget {
static const platform = const MethodChannel('samples.flutter.dev/navigation_channel');
Future<void> _pushOnNative() async {
try {
Map parameters = Map();
parameters["title"] = "Contact Details";
parameters["name"] = "Bang Operator";
parameters["so_profile_exists"] = true;
await platform.invokeMethod('push',[parameters]);
} on PlatformException catch (e) {
print("Failed to communicate level: '${e.message}'.");
}
}
@override
Widget build(BuildContext context) {
return Center(
child: FlatButton(
textColor: Colors.white,
color: Colors.red,
onPressed: _pushOnNative,
child: Text('Push Me'),
)
);
}
}
在 iOS 應用端,我們需要觀察通道samples.flutter.dev/navigation_channel
的方法 'push'。 我們也可以從 flutter 端傳遞參數,在這個例子中,我們傳遞一個 Map(Dart),它作為 NSDictionary(Obj-C) 接收
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GeneratedPluginRegistrant registerWithRegistry:self];
FlutterViewController *controller = (FlutterViewController*)self.window.rootViewController;
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:controller];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = navigationController;
[navigationController setNavigationBarHidden:YES animated:YES];
[self.window makeKeyAndVisible];
[self setupNavigationChannelCallbacksOnMessenger:controller
forNavigationController:navigationController];
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
- (void)setupNavigationChannelCallbacksOnMessenger:(id<FlutterBinaryMessenger>)messenger
forNavigationController:(UINavigationController *)navigationController {
FlutterMethodChannel* pushChannel = [FlutterMethodChannel
methodChannelWithName:@"samples.flutter.dev/navigation_channel"
binaryMessenger:messenger];
[pushChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
if ([call.method isEqualToString:@"push"] && [self getDictionaryFromArguments:call.arguments]) {
NSDictionary *parameters = [self getDictionaryFromArguments:call.arguments];
[self pushContactScreenWithInfo:parameters onNaivgationController:navigationController];
result(@(true));
} else {
result(FlutterMethodNotImplemented);
}
}];
}
- (NSDictionary *)getDictionaryFromArguments:(id)arguments {
if (![arguments isKindOfClass:[NSArray class]]) {
return nil;
}
NSArray *argumentsArray = (NSArray *)arguments;
if (argumentsArray.firstObject == nil || ![argumentsArray.firstObject isKindOfClass:[NSDictionary class]]) {
return nil;
}
return (NSDictionary *)argumentsArray.firstObject;
}
- (void)pushContactScreenWithInfo:(NSDictionary *)info
onNaivgationController:(UINavigationController *)navigationContorller {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
ContactViewController *controller = [storyboard instantiateViewControllerWithIdentifier:@"ContactViewController"];
[navigationContorller pushViewController:controller animated:YES];
[controller view];
[controller configureWithInfo:info];
}
在 Swift 中,我們可以使用方法通道從 Flutter 動作事件中打開原生 iOS viewController,在 Flutter 中,您需要添加以下幾行來觸發原生 iOS 方法。 在您的操作方法中添加這些行
var platform = const MethodChannel('navigation');
final String result = await platform.invokeMethod('IOS');
在 iOS 中,在 AppDelegate 應用程序方法中添加以下幾行。
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let methodChannel = FlutterMethodChannel(name: "navigation", binaryMessenger:controller.binaryMessenger)
navigationController = UINavigationController(rootViewController: controller)
navigationController.setNavigationBarHidden(true, animated: false)
self.window!.rootViewController = navigationController
self.window!.makeKeyAndVisible()
methodChannel.setMethodCallHandler({
(call: FlutterMethodCall, result: @escaping FlutterResult) ->
Void in
if call.method == "IOS" {
let vc = "Your viewController"(nibName: "Your
viewController", bundle: nil)
navigationController.pushViewController(vc, animated:
false)
} else {
result(FlutterMethodNotImplemented)
return
}
})
本機視圖控制器后退按鈕操作。
self.navigationController?.popViewController(animated: true)
謝謝。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.