aboutsummaryrefslogtreecommitdiffstats
path: root/iPhone/CordovaLib/Classes/CDVSplashScreen.m
diff options
context:
space:
mode:
Diffstat (limited to 'iPhone/CordovaLib/Classes/CDVSplashScreen.m')
-rwxr-xr-xiPhone/CordovaLib/Classes/CDVSplashScreen.m186
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];
+ }];
}
}