diff options
Diffstat (limited to 'iPhone/CordovaLib/Classes/CDVSplashScreen.m')
-rwxr-xr-x | iPhone/CordovaLib/Classes/CDVSplashScreen.m | 186 |
1 files changed, 121 insertions, 65 deletions
diff --git a/iPhone/CordovaLib/Classes/CDVSplashScreen.m b/iPhone/CordovaLib/Classes/CDVSplashScreen.m index cba1b53..fdb79fa 100755 --- a/iPhone/CordovaLib/Classes/CDVSplashScreen.m +++ b/iPhone/CordovaLib/Classes/CDVSplashScreen.m @@ -19,29 +19,25 @@ #import "CDVSplashScreen.h" -#define kSplashScreenStateShow 0 -#define kSplashScreenStateHide 1 - #define kSplashScreenDurationDefault 0.25f @implementation CDVSplashScreen - (void)pluginInitialize { - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pageDidLoad) name:CDVPageDidLoadNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onOrientationWillChange:) name:UIApplicationWillChangeStatusBarOrientationNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pageDidLoad) name:CDVPageDidLoadNotification object:self.webView]; - [self show:nil]; + [self setVisible:YES]; } - (void)show:(CDVInvokedUrlCommand*)command { - [self updateSplashScreenWithState:kSplashScreenStateShow]; + [self setVisible:YES]; } - (void)hide:(CDVInvokedUrlCommand*)command { - [self updateSplashScreenWithState:kSplashScreenStateHide]; + [self setVisible:NO]; } - (void)pageDidLoad @@ -50,16 +46,13 @@ // if value is missing, default to yes if ((autoHideSplashScreenValue == nil) || [autoHideSplashScreenValue boolValue]) { - [self hide:nil]; + [self setVisible:NO]; } } -- (void)onOrientationWillChange:(NSNotification*)notification +- (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context { - if (_imageView != nil) { - UIInterfaceOrientation orientation = [notification.userInfo[UIApplicationStatusBarOrientationUserInfoKey] intValue]; - [self updateSplashImageForOrientation:orientation]; - } + [self updateImage]; } - (void)createViews @@ -83,43 +76,125 @@ topActivityIndicatorStyle = UIActivityIndicatorViewStyleGray; } + UIView* parentView = self.viewController.view; + parentView.userInteractionEnabled = NO; // disable user interaction while splashscreen is shown _activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:topActivityIndicatorStyle]; - _activityView.tag = 2; - _activityView.center = self.viewController.view.center; + _activityView.center = CGPointMake(parentView.bounds.size.width / 2, parentView.bounds.size.height / 2); + _activityView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin + | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin; [_activityView startAnimating]; + // Set the frame & image later. _imageView = [[UIImageView alloc] init]; - [self.viewController.view addSubview:_imageView]; - [self.viewController.view.superview addSubview:_activityView]; - [self.viewController.view.superview layoutSubviews]; + [parentView addSubview:_imageView]; + + id showSplashScreenSpinnerValue = [self.commandDelegate.settings objectForKey:@"ShowSplashScreenSpinner"]; + // backwards compatibility - if key is missing, default to true + if ((showSplashScreenSpinnerValue == nil) || [showSplashScreenSpinnerValue boolValue]) { + [parentView addSubview:_activityView]; + } + + // Frame is required when launching in portrait mode. + // Bounds for landscape since it captures the rotation. + [parentView addObserver:self forKeyPath:@"frame" options:0 context:nil]; + [parentView addObserver:self forKeyPath:@"bounds" options:0 context:nil]; + + [self updateImage]; } -- (void)updateSplashImageForOrientation:(UIInterfaceOrientation)orientation +- (void)destroyViews { - // IPHONE (default) - NSString* imageName = @"Default"; + [_imageView removeFromSuperview]; + [_activityView removeFromSuperview]; + _imageView = nil; + _activityView = nil; + _curImageName = nil; + + self.viewController.view.userInteractionEnabled = YES; // re-enable user interaction upon completion + [self.viewController.view removeObserver:self forKeyPath:@"frame"]; + [self.viewController.view removeObserver:self forKeyPath:@"bounds"]; +} + +// Sets the view's frame and image. +- (void)updateImage +{ + UIInterfaceOrientation orientation = self.viewController.interfaceOrientation; + + // Use UILaunchImageFile if specified in plist. Otherwise, use Default. + NSString* imageName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UILaunchImageFile"]; + + if (imageName) { + imageName = [imageName stringByDeletingPathExtension]; + } else { + imageName = @"Default"; + } if (CDV_IsIPhone5()) { imageName = [imageName stringByAppendingString:@"-568h"]; } else if (CDV_IsIPad()) { - // set default to portrait upside down - imageName = @"Default-Portrait"; // @"Default-PortraitUpsideDown.png"; + switch (orientation) { + case UIInterfaceOrientationLandscapeLeft: + case UIInterfaceOrientationLandscapeRight: + imageName = [imageName stringByAppendingString:@"-Landscape"]; + break; + + case UIInterfaceOrientationPortrait: + case UIInterfaceOrientationPortraitUpsideDown: + default: + imageName = [imageName stringByAppendingString:@"-Portrait"]; + break; + } + } - if (orientation == UIInterfaceOrientationLandscapeLeft) { - imageName = @"Default-Landscape.png"; // @"Default-LandscapeLeft.png"; - } else if (orientation == UIInterfaceOrientationLandscapeRight) { - imageName = @"Default-Landscape.png"; // @"Default-LandscapeRight.png"; + if (![imageName isEqualToString:_curImageName]) { + UIImage* img = [UIImage imageNamed:imageName]; + _imageView.image = img; + _curImageName = imageName; + } + + // Check that splash screen's image exists before updating bounds + if (_imageView.image) { + [self updateBounds]; + } else { + NSLog(@"WARNING: The splashscreen image named %@ was not found", imageName); + } +} + +- (void)updateBounds +{ + UIImage* img = _imageView.image; + CGRect imgBounds = CGRectMake(0, 0, img.size.width, img.size.height); + + CGSize screenSize = [self.viewController.view convertRect:[UIScreen mainScreen].bounds fromView:nil].size; + + // There's a special case when the image is the size of the screen. + if (CGSizeEqualToSize(screenSize, imgBounds.size)) { + CGRect statusFrame = [self.viewController.view convertRect:[UIApplication sharedApplication].statusBarFrame fromView:nil]; + imgBounds.origin.y -= statusFrame.size.height; + } else { + CGRect viewBounds = self.viewController.view.bounds; + CGFloat imgAspect = imgBounds.size.width / imgBounds.size.height; + CGFloat viewAspect = viewBounds.size.width / viewBounds.size.height; + // This matches the behaviour of the native splash screen. + CGFloat ratio; + if (viewAspect > imgAspect) { + ratio = viewBounds.size.width / imgBounds.size.width; + } else { + ratio = viewBounds.size.height / imgBounds.size.height; } + imgBounds.size.height *= ratio; + imgBounds.size.width *= ratio; } - _imageView.image = [UIImage imageNamed:imageName]; - _imageView.frame = CGRectMake(0, 0, _imageView.image.size.width, _imageView.image.size.height); + _imageView.frame = imgBounds; } -- (void)updateSplashScreenWithState:(int)state +- (void)setVisible:(BOOL)visible { - float toAlpha = state == kSplashScreenStateShow ? 1.0f : 0.0f; - BOOL hidden = state == kSplashScreenStateShow ? NO : YES; + if (visible == _visible) { + return; + } + _visible = visible; id fadeSplashScreenValue = [self.commandDelegate.settings objectForKey:@"FadeSplashScreen"]; id fadeSplashScreenDuration = [self.commandDelegate.settings objectForKey:@"FadeSplashScreenDuration"]; @@ -129,45 +204,26 @@ if ((fadeSplashScreenValue == nil) || ![fadeSplashScreenValue boolValue]) { fadeDuration = 0; } - if (hidden && (_imageView == nil)) { - return; - } else if (_imageView == nil) { - [self createViews]; - fadeDuration = 0; - } - if (!hidden) { - [self updateSplashImageForOrientation:self.viewController.interfaceOrientation]; - } - - if (fadeDuration == 0) { - [_imageView setHidden:hidden]; - [_activityView setHidden:hidden]; - } else { - if (state == kSplashScreenStateShow) { - // reset states - [_imageView setHidden:NO]; - [_activityView setHidden:NO]; - [_imageView setAlpha:0.0f]; - [_activityView setAlpha:0.0f]; + // Never animate the showing of the splash screen. + if (visible) { + if (_imageView == nil) { + [self createViews]; } - + } else if (fadeDuration == 0) { + [self destroyViews]; + } else { [UIView transitionWithView:self.viewController.view duration:fadeDuration options:UIViewAnimationOptionTransitionNone animations:^(void) { - [_imageView setAlpha:toAlpha]; - [_activityView setAlpha:toAlpha]; - } + [_imageView setAlpha:0]; + [_activityView setAlpha:0]; + } + completion:^(BOOL finished) { - if (state == kSplashScreenStateHide) { - // Clean-up resources. - [_imageView removeFromSuperview]; - [_activityView removeFromSuperview]; - _imageView = nil; - _activityView = nil; - } - }]; + [self destroyViews]; + }]; } } |