-
-
Save stevetranby/32ebaee5f2335832ec5882dccc57396e to your computer and use it in GitHub Desktop.
RootViewController snippet to support iPhone X Safe Area
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@implementation RootViewController | |
// Implement loadView to create a view hierarchy programmatically, without using a nib. | |
- (void)loadView { | |
// Initialize the CCEAGLView | |
CGFloat nscale = [[UIScreen mainScreen] nativeScale]; | |
NSLog(@"window.nativescale = %f", nscale); | |
printf("window.nativescale = %f\n", nscale); | |
CGRect nbounds = [[UIScreen mainScreen] nativeBounds]; | |
NSLog(@"window.nativeBounds = %@", NSStringFromCGRect(nbounds)); | |
printf("window.nativeBounds = %f x %f\n", nbounds.size.width, nbounds.size.height); | |
CGRect screenBounds = [UIScreen mainScreen].bounds; | |
NSLog(@"screenBounds = %@", NSStringFromCGRect(screenBounds)); | |
printf("screenBounds = %f x %f\n", screenBounds.size.width, screenBounds.size.height); | |
// NOTE(steve): create the background view that will display outside the safe area | |
UIView* backgroundView = [[UIView alloc] initWithFrame:screenBounds]; | |
//[backgroundView setBackgroundColor:[UIColor magentaColor]]; // Debug/Test | |
[backgroundView setBackgroundColor:[UIColor blackColor]]; | |
self.view = backgroundView; | |
// NOTE(steve): Moving into didAppear in order to have valid safe area insets | |
// CCEAGLView *eaglView = [CCEAGLView viewWithFrame:screenBounds | |
// pixelFormat: (__bridge NSString *)cocos2d::GLViewImpl::_pixelFormat | |
// depthFormat: cocos2d::GLViewImpl::_depthFormat | |
// preserveBackbuffer: NO | |
// sharegroup: nil | |
// multiSampling: NO | |
// numberOfSamples: 0 ]; | |
// | |
// eaglView.contentScaleFactor = [[UIScreen mainScreen] nativeScale]; | |
// | |
// // Enable or disable multiple touches | |
// [eaglView setMultipleTouchEnabled:YES]; | |
// | |
// // Set EAGLView as view of RootViewController | |
// [self.view addSubview:eaglView]; | |
// | |
// //cocos2d::GLView *glview = cocos2d::GLViewImpl::createWithEAGLView((__bridge void *)self.view); | |
// cocos2d::GLView *glview = cocos2d::GLViewImpl::createWithEAGLView((__bridge void *)eaglView); | |
// | |
// //set the GLView as OpenGLView of the Director | |
// cocos2d::Director::getInstance()->setOpenGLView(glview); | |
// | |
// | |
// //run the cocos2d-x game scene | |
// app->run(); | |
} | |
- (void)safeAreaInsetsDidChange { | |
NSLog(@"safeAreaInsetsDidChange called ...."); | |
} | |
// Implement viewDidLoad to do additional setup after loading the view | |
- (void)viewDidLoad { | |
[super viewDidLoad]; | |
if (@available(iOS 11.0, *)) { | |
// This should only be necessary if you changed the return value of the property | |
// `BOOL preferredScreenEdgesDeferringSystemGestures`, but in limited testing needed this | |
[self setNeedsUpdateOfScreenEdgesDeferringSystemGestures]; | |
} else { | |
// Fallback on earlier versions | |
} | |
} | |
- (void)viewWillAppear:(BOOL)animated { | |
[super viewWillAppear:animated]; | |
if (@available(iOS 11.0, *)) { | |
[self setNeedsUpdateOfScreenEdgesDeferringSystemGestures]; | |
} else { | |
// Fallback on earlier versions | |
} | |
} | |
- (void)viewDidAppear:(BOOL)animated { | |
[super viewDidAppear:animated]; | |
// NOTE(steve): may want to check if insets are valid in willappear to avoid any possible "blink" due to creating/adding view after already on screen | |
// NOTE(steve): could also use the LayoutGuide instead | |
// check for devices with safe area | |
CGRect safeViewBounds = self.view.bounds; | |
if (@available(iOS 11.0, *)) | |
{ | |
BOOL hasSafeArea = self.view.insetsLayoutMarginsFromSafeArea; | |
NSLog(@"hasSafeArea = %d", hasSafeArea); | |
UIEdgeInsets safeInsets = self.view.safeAreaInsets; | |
CGSize size = safeViewBounds.size; | |
CGPoint origin = safeViewBounds.origin; | |
NSLog(@"safeInsets = %@", safeInsets); | |
// NOTE(steve): remember UIView frame is "Y flipped" => origin @ top-left | |
safeViewBounds = CGRectMake(origin.x + safeInsets.left, | |
origin.y + safeInsets.top, | |
size.width - safeInsets.left - safeInsets.right, | |
size.height - safeInsets.top - safeInsets.bottom); | |
NSLog(@"safeViewBounds = %@", safeViewBounds); | |
} else { | |
// Fallback on earlier versions | |
// NOTE(steve): don't do anything for older phones | |
} | |
cocos2d::Application *app = cocos2d::Application::getInstance(); | |
// Initialize the GLView attributes | |
app->initGLContextAttrs(); | |
cocos2d::GLViewImpl::convertAttrs(); | |
CCEAGLView *eaglView = [CCEAGLView viewWithFrame:safeViewBounds | |
pixelFormat: (__bridge NSString *)cocos2d::GLViewImpl::_pixelFormat | |
depthFormat: cocos2d::GLViewImpl::_depthFormat | |
preserveBackbuffer: NO | |
sharegroup: nil | |
multiSampling: NO | |
numberOfSamples: 0 ]; | |
eaglView.contentScaleFactor = [[UIScreen mainScreen] nativeScale]; | |
// Enable or disable multiple touches | |
[eaglView setMultipleTouchEnabled:YES]; | |
// Set EAGLView as view of RootViewController | |
[self.view addSubview:eaglView]; | |
//cocos2d::GLView *glview = cocos2d::GLViewImpl::createWithEAGLView((__bridge void *)self.view); | |
cocos2d::GLView *glview = cocos2d::GLViewImpl::createWithEAGLView((__bridge void *)eaglView); | |
//set the GLView as OpenGLView of the Director | |
cocos2d::Director::getInstance()->setOpenGLView(glview); | |
//run the cocos2d-x game scene | |
app->run(); | |
} | |
- (void)viewDidDisappear:(BOOL)animated { | |
[super viewDidDisappear:animated]; | |
} | |
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { | |
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation]; | |
auto glview = cocos2d::Director::getInstance()->getOpenGLView(); | |
if (glview) | |
{ | |
CCEAGLView *eaglview = (__bridge CCEAGLView *)glview->getEAGLView(); | |
if (eaglview) | |
{ | |
CGSize s = CGSizeMake([eaglview getWidth], [eaglview getHeight]); | |
cocos2d::Application::getInstance()->applicationScreenSizeChanged((int) s.width, (int) s.height); | |
} | |
} | |
if (@available(iOS 11.0, *)) { | |
[self setNeedsUpdateOfScreenEdgesDeferringSystemGestures]; | |
} else { | |
// Fallback on earlier versions | |
} | |
} | |
- (BOOL)shouldAutorotate { | |
return YES; | |
} | |
//fix not hide status on ios7 | |
- (BOOL)prefersStatusBarHidden { | |
return YES; | |
} | |
- (BOOL)prefersHomeIndicatorAutoHidden { | |
// NOTE(steve): setting this to yes causes the defer system edge gestures to not work | |
//return YES; | |
return NO; | |
} | |
- (UIRectEdge)preferredScreenEdgesDeferringSystemGestures | |
{ | |
return UIRectEdgeAll; | |
// NOTE(steve): should probably just defer the bottom swipe (home gesture) | |
//return UIRectEdgeBottom; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment