Flutter Engine
The Flutter Engine
main.mm
Go to the documentation of this file.
1// Copyright 2019 Google LLC.
2// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
3
6
8
9#import <UIKit/UIKit.h>
10
11#include <cstdlib>
12
13@interface AppViewController : UIViewController
14 @property (strong) SkiaContext* skiaContext;
15 @property (strong) UIStackView* stackView;
16@end
17
18@implementation AppViewController
19
20- (void)loadView {
21 [self setView:[[UIView alloc] init]];
22}
23
24- (void)viewDidLoad {
25 [super viewDidLoad];
26 if (![self skiaContext]) {
27 #if (defined(SK_GANESH) && defined(SK_METAL) && !defined(SK_BUILD_FOR_GOOGLE3))
28 [self setSkiaContext:MakeSkiaMetalContext()];
29 #elif (defined(SK_GANESH) && defined(SK_GL) && !defined(SK_BUILD_FOR_GOOGLE3))
30 [self setSkiaContext:MakeSkiaGLContext()];
31 #else
32 [self setSkiaContext:MakeSkiaUIContext()];
33 #endif
34 if (![self skiaContext]) {
35 NSLog(@"abort: failed to make skia context.");
36 std::abort();
37 }
38 }
39 CGFloat screenWidth = [[UIScreen mainScreen] bounds].size.width;
40
41 UIStackView* stack = [[UIStackView alloc] init];
42 [stack setAxis:UILayoutConstraintAxisVertical];
43 [stack setDistribution:UIStackViewDistributionEqualSpacing];
44
45 NSBundle* mainBundle = [NSBundle mainBundle];
46 NSArray<NSString*>* paths = [mainBundle pathsForResourcesOfType:@"json"
47 inDirectory:@"data"];
48 constexpr CGFloat kSpacing = 2;
49 CGFloat totalHeight = kSpacing;
50 for (NSUInteger i = 0; i < [paths count]; ++i) {
51 NSString* path = [paths objectAtIndex:i];
52 NSData* content = [NSData dataWithContentsOfFile:path];
53 if (!content) {
54 NSLog(@"'%@' not found", path);
55 continue;
56 }
57 SkottieViewController* controller = [[SkottieViewController alloc] init];
58 if (![controller loadAnimation:content]) {
59 continue;
60 }
61 CGSize animSize = [controller size];
62 CGFloat height = animSize.width ? (screenWidth * animSize.height / animSize.width) : 0;
63 CGRect frame = {{0, 0}, {screenWidth, height}};
64 UIView* skiaView = [[self skiaContext] makeViewWithController:controller withFrame:frame];
65 [[[skiaView heightAnchor] constraintEqualToConstant:height] setActive:true];
66 [[[skiaView widthAnchor] constraintEqualToConstant:screenWidth] setActive:true];
67 [skiaView setNeedsDisplay];
68 [stack addArrangedSubview:skiaView];
69 totalHeight += height + kSpacing;
70 }
71 [stack setFrame:{{0, 0}, {screenWidth, totalHeight}}];
72 [stack setNeedsDisplay];
73
74 CGFloat statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height;
75 CGSize mainScreenSize = [[UIScreen mainScreen] bounds].size;
76 CGRect scrollViewBounds = {{0, statusBarHeight},
77 {mainScreenSize.width, mainScreenSize.height - statusBarHeight}};
78 UIScrollView* scrollView = [[UIScrollView alloc] initWithFrame:scrollViewBounds];
79 [scrollView setContentSize:[stack frame].size];
80 [scrollView addSubview:stack];
81 [scrollView setBackgroundColor:[UIColor blackColor]];
82 [scrollView setNeedsDisplay];
83
84 [self setStackView:stack];
85
86 UIView* mainView = [self view];
87 [mainView setBounds:{{0, 0}, mainScreenSize}];
88 [mainView setBackgroundColor:[UIColor whiteColor]];
89 [mainView addSubview:scrollView];
90 [mainView setNeedsDisplay];
91
92 UITapGestureRecognizer* tapGestureRecognizer = [[UITapGestureRecognizer alloc] init];
93 [tapGestureRecognizer addTarget:self action:@selector(handleTap:)];
94 [mainView addGestureRecognizer:tapGestureRecognizer];
95}
96
97- (void)handleTap:(UIGestureRecognizer*)sender {
98 if ([sender state] != UIGestureRecognizerStateEnded) {
99 return;
100 }
101 NSArray<UIView*>* subviews = [[self stackView] subviews];
102 for (NSUInteger i = 0; i < [subviews count]; ++i) {
103 UIView* uIView = [subviews objectAtIndex:i];
104 if (SkiaViewController* controller = [[self skiaContext] getViewController:uIView]) {
105 [controller togglePaused];
106 [uIView setNeedsDisplay];
107 }
108 }
109}
110@end
111
112@interface AppDelegate : UIResponder <UIApplicationDelegate>
113 @property (strong, nonatomic) UIWindow* window;
114@end
115
116@implementation AppDelegate
117
118- (BOOL)application:(UIApplication*)app didFinishLaunchingWithOptions:(NSDictionary*)ops {
119 [self setWindow:[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]];
120 [[self window] setRootViewController:[[AppViewController alloc] init]];
121 [[self window] makeKeyAndVisible];
122 return YES;
123}
124@end
125
126int main(int argc, char* argv[]) {
127 @autoreleasepool {
128 return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
129 }
130}
GLFWwindow * window
Definition: main.cc:45
double frame
Definition: examples.cpp:31
AtkStateType state
SkiaContext * skiaContext
Definition: main.mm:14
UIStackView * stackView
Definition: main.mm:15
void loadView()
Definition: main.mm:98
void viewDidLoad()
Definition: main.mm:102
union flutter::testing::@2836::KeyboardChange::@76 content
char ** argv
Definition: library.h:9
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
int32_t height
int main(int argc, char *argv[])
Definition: main.mm:8
int BOOL
Definition: windows_types.h:37