// Copyright 2014 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #import "MainViewController.h" #import "AppDelegate.h" #import "DualFlutterViewController.h" #import "FullScreenViewController.h" #import "HybridViewController.h" #import "NativeViewController.h" @interface MainViewController () @property (weak, nonatomic) UIButton* flutterViewWarmButton; @end @implementation MainViewController { UIStackView *_stackView; } - (void)viewDidLoad { [super viewDidLoad]; [self.view setFrame:self.view.window.bounds]; self.title = @"Flutter iOS Demos Home"; self.view.backgroundColor = UIColor.whiteColor; _stackView = [[UIStackView alloc] initWithFrame:self.view.frame]; _stackView.axis = UILayoutConstraintAxisVertical; _stackView.distribution = UIStackViewDistributionEqualSpacing; _stackView.alignment = UIStackViewAlignmentCenter; _stackView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; _stackView.layoutMargins = UIEdgeInsetsMake(0, 0, 50, 0); _stackView.layoutMarginsRelativeArrangement = YES; [self.view addSubview:_stackView]; [self addButton:@"Native iOS View" action:@selector(showNative)]; [self addButton:@"Full Screen (Cold)" action:@selector(showFullScreenCold)]; [self addButton:@"Full Screen (Warm)" action:@selector(showFullScreenWarm)]; self.flutterViewWarmButton = [self addButton:@"Flutter View (Warm)" action:@selector(showFlutterViewWarm)]; [self addButton:@"Hybrid View (Warm)" action:@selector(showHybridView)]; [self addButton:@"Dual Flutter View (Cold)" action:@selector(showDualView)]; } - (FlutterEngine *)engine { return [(AppDelegate *)[[UIApplication sharedApplication] delegate] engine]; } - (FlutterBasicMessageChannel*)reloadMessageChannel { return [(AppDelegate *)[[UIApplication sharedApplication] delegate] reloadMessageChannel]; } - (void)showDualView { DualFlutterViewController *dualViewController = [[DualFlutterViewController alloc] init]; [self.navigationController pushViewController:dualViewController animated:YES]; } - (void)showHybridView { HybridViewController *hybridViewController = [[HybridViewController alloc] init]; [self.navigationController pushViewController:hybridViewController animated:YES]; } - (void)showNative { NativeViewController *nativeViewController = [[NativeViewController alloc] init]; [self.navigationController pushViewController:nativeViewController animated:YES]; } - (void)showFullScreenCold { FullScreenViewController *flutterViewController = [[FullScreenViewController alloc] init]; [flutterViewController setInitialRoute:@"full"]; [[self reloadMessageChannel] sendMessage:@"full"]; [self.navigationController pushViewController:flutterViewController animated:NO]; // Animating this is janky because of // transitions with header on the native side. // It's especially bad with a cold engine. } - (void)showFullScreenWarm { [[self engine].navigationChannel invokeMethod:@"setInitialRoute" arguments:@"full"]; [[self reloadMessageChannel] sendMessage:@"full"]; FullScreenViewController *flutterViewController = [[FullScreenViewController alloc] initWithEngine:[self engine] nibName:nil bundle:nil]; [self.navigationController pushViewController:flutterViewController animated:NO]; // Animating this is problematic. } - (void)showFlutterViewWarm { self.flutterViewWarmButton.backgroundColor = UIColor.redColor; FlutterEngine *engine = [self engine]; FlutterBasicMessageChannel* messageChannel = [self reloadMessageChannel]; NSAssert(engine != nil, @"Engine is not nil."); NSAssert(engine.navigationChannel != nil, @"Engine.navigationChannel is not nil."); NSAssert(messageChannel != nil, @"messageChannel is not nil."); [engine.navigationChannel invokeMethod:@"setInitialRoute" arguments:@"/"]; [messageChannel sendMessage:@"/"]; FlutterViewController *flutterViewController = [[FlutterViewController alloc] initWithEngine:[self engine] nibName:nil bundle:nil]; flutterViewController.view.accessibilityLabel = @"flutter view"; NSAssert(self.navigationController != nil, @"self.navigationController is not nil."); [self.navigationController pushViewController:flutterViewController animated:NO]; if (self.navigationController.topViewController != flutterViewController) { // For debugging: // Some unknown issue happened caused `flutterViewController` not being pushed. // We try to push an basic UIViewController to see if it would work. UIViewController *viewController = [[UIViewController alloc] init]; viewController.view.backgroundColor = UIColor.blueColor; [self.navigationController pushViewController:viewController animated:NO]; NSAssert(self.navigationController.topViewController == viewController, @"self.navigationController.topViewController should be the basic view controller"); } } - (UIButton *)addButton:(NSString *)title action:(SEL)action { UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; [button setTitle:title forState:UIControlStateNormal]; [button addTarget:self action:action forControlEvents:UIControlEventTouchUpInside]; [_stackView addArrangedSubview:button]; return button; } @end