Skip to content

Commit

Permalink
added blurred background and support for orientation switching
Browse files Browse the repository at this point in the history
  • Loading branch information
cezarywojcik committed Sep 5, 2013
1 parent 22d90e7 commit 942999d
Show file tree
Hide file tree
Showing 8 changed files with 179 additions and 30 deletions.
161 changes: 139 additions & 22 deletions CWPopup/UIViewController+CWPopup.m
Expand Up @@ -10,26 +10,101 @@
#import <objc/runtime.h>
#import <QuartzCore/QuartzCore.h>

#define ANIMATION_TIME 0.5
#define FADE_ALPHA 0.4
// image blurring from http://stackoverflow.com/a/8916196

@interface UIImage (ImageBlur)
- (UIImage *)getImageWithBlur;
@end

@implementation UIImage (ImageBlur)
- (UIImage *)getImageWithBlur {
float weight[5] = {0.2270270270, 0.1945945946, 0.1216216216, 0.0540540541, 0.0162162162};
// Blur horizontally
UIGraphicsBeginImageContext(self.size);
[self drawInRect:CGRectMake(0, 0, self.size.width, self.size.height) blendMode:kCGBlendModePlusLighter alpha:weight[0]];
for (int x = 1; x < 5; ++x) {
[self drawInRect:CGRectMake(x, 0, self.size.width, self.size.height) blendMode:kCGBlendModePlusLighter alpha:weight[x]];
[self drawInRect:CGRectMake(-x, 0, self.size.width, self.size.height) blendMode:kCGBlendModePlusLighter alpha:weight[x]];
}
UIImage *horizontallyBlurredImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Blur vertically
UIGraphicsBeginImageContext(self.size);
[horizontallyBlurredImage drawInRect:CGRectMake(0, 0, self.size.width, self.size.height) blendMode:kCGBlendModePlusLighter alpha:weight[0]];
for (int y = 1; y < 5; ++y) {
[horizontallyBlurredImage drawInRect:CGRectMake(0, y, self.size.width, self.size.height) blendMode:kCGBlendModePlusLighter alpha:weight[y]];
[horizontallyBlurredImage drawInRect:CGRectMake(0, -y, self.size.width, self.size.height) blendMode:kCGBlendModePlusLighter alpha:weight[y]];
}
UIImage *blurredImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//
return blurredImage;
}
@end

#define ANIMATION_TIME 0.5f
#define FADE_ALPHA 1.0f
#define STATUS_BAR_SIZE 22

NSString const *CWPopupKey = @"CWPopupkey";
NSString const *CWFadeViewKey = @"CWFadeViewKey";
NSString const *CWBlurViewKey = @"CWFadeViewKey";

@implementation UIViewController (CWPopup)

@dynamic popupViewController;

#pragma mark - blur view methods

- (UIImage *)getScreenImage {
// frame without status bar
CGRect frame;
if (UIDeviceOrientationIsPortrait([UIDevice currentDevice].orientation)) {
frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
} else {
frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.height, [UIScreen mainScreen].bounds.size.width);
}
// begin image context
UIGraphicsBeginImageContext(frame.size);
// get current context
CGContextRef currentContext = UIGraphicsGetCurrentContext();
// draw current view
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
// clip context to frame
CGContextClipToRect(currentContext, frame);
// get resulting cropped screenshot
UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext();
// end image context
UIGraphicsEndImageContext();
return screenshot;
}

- (UIImage *)getBlurredImage:(UIImage *)imageToBlur {
return [[imageToBlur getImageWithBlur] getImageWithBlur];
}

- (void)addBlurView {
UIImageView *blurView = [UIImageView new];
if (UIDeviceOrientationIsPortrait([UIDevice currentDevice].orientation)) {
blurView.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
} else {
blurView.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.height, [UIScreen mainScreen].bounds.size.width);
}
blurView.alpha = 0.0f;
blurView.image = [self getBlurredImage:[self getScreenImage]];
[self.view addSubview:blurView];
[self.view bringSubviewToFront:self.popupViewController.view];
objc_setAssociatedObject(self, &CWBlurViewKey, blurView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

#pragma mark - present/dismiss

- (void)presentPopupViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion {
// setup
// initial setup
self.popupViewController = viewControllerToPresent;
CGRect frame = viewControllerToPresent.view.frame;
CGFloat x = ([UIScreen mainScreen].bounds.size.width - viewControllerToPresent.view.frame.size.width)/2;
CGFloat y =([UIScreen mainScreen].bounds.size.height - viewControllerToPresent.view.frame.size.height)/2;
CGRect finalFrame = CGRectMake(x, y, frame.size.width, frame.size.height);
// parallax setup
self.popupViewController.view.autoresizesSubviews = NO;
self.popupViewController.view.autoresizingMask = UIViewAutoresizingNone;
CGRect finalFrame = [self getPopupFrameForViewController:viewControllerToPresent];
// parallax setup if iOS7+
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
UIInterpolatingMotionEffect *interpolationHorizontal = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];
interpolationHorizontal.minimumRelativeValue = @-10.0;
Expand All @@ -48,20 +123,17 @@ - (void)presentPopupViewController:(UIViewController *)viewControllerToPresent a
viewControllerToPresent.view.layer.shadowPath = [UIBezierPath bezierPathWithRect:viewControllerToPresent.view.layer.bounds].CGPath;
// rounded corners
viewControllerToPresent.view.layer.cornerRadius = 5.0f;
// black uiview
UIView *fadeView = [UIView new];
fadeView.frame = [UIScreen mainScreen].bounds;
fadeView.backgroundColor = [UIColor blackColor];
fadeView.alpha = 0.0f;
[self.view addSubview:fadeView];
objc_setAssociatedObject(self, &CWFadeViewKey, fadeView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
// blurview
[self addBlurView];
UIView *blurView = objc_getAssociatedObject(self, &CWBlurViewKey);
// setup
if (flag) { // animate
CGRect initialFrame = CGRectMake(finalFrame.origin.x, [UIScreen mainScreen].bounds.size.height + viewControllerToPresent.view.frame.size.height/2, finalFrame.size.width, finalFrame.size.height);
viewControllerToPresent.view.frame = initialFrame;
[self.view addSubview:viewControllerToPresent.view];
[UIView animateWithDuration:ANIMATION_TIME delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
viewControllerToPresent.view.frame = finalFrame;
fadeView.alpha = FADE_ALPHA;
blurView.alpha = FADE_ALPHA;
} completion:^(BOOL finished) {
[completion invoke];
}];
Expand All @@ -70,31 +142,76 @@ - (void)presentPopupViewController:(UIViewController *)viewControllerToPresent a
[self.view addSubview:viewControllerToPresent.view];
[completion invoke];
}
// if screen orientation changed
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(screenOrientationChanged) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
}

- (void)dismissPopupViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion {
UIView *fadeView = objc_getAssociatedObject(self, &CWFadeViewKey);
UIView *blurView = objc_getAssociatedObject(self, &CWBlurViewKey);
if (flag) { // animate
CGRect initialFrame = self.popupViewController.view.frame;
[UIView animateWithDuration:ANIMATION_TIME delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.popupViewController.view.frame = CGRectMake(initialFrame.origin.x, [UIScreen mainScreen].bounds.size.height + initialFrame.size.height/2, initialFrame.size.width, initialFrame.size.height);
// uncomment the line below to have slight rotation during the dismissal
// self.popupViewController.view.transform = CGAffineTransformMakeRotation(M_PI/6);
fadeView.alpha = 0.0f;
blurView.alpha = 0.0f;
} completion:^(BOOL finished) {
[self.popupViewController.view removeFromSuperview];
[fadeView removeFromSuperview];
[blurView removeFromSuperview];
self.popupViewController = nil;
[completion invoke];
}];
} else { // don't animate
[self.popupViewController.view removeFromSuperview];
[fadeView removeFromSuperview];
[blurView removeFromSuperview];
self.popupViewController = nil;
fadeView = nil;
blurView = nil;

[completion invoke];
}
// remove observer
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

#pragma mark - handling screen orientation change

- (CGRect)getPopupFrameForViewController:(UIViewController *)viewController {
CGRect frame = viewController.view.frame;
CGFloat x;
CGFloat y;
if (UIDeviceOrientationIsPortrait([UIDevice currentDevice].orientation)) {
x = ([UIScreen mainScreen].bounds.size.width - frame.size.width)/2;
y = ([UIScreen mainScreen].bounds.size.height - frame.size.height)/2;
} else {
x = ([UIScreen mainScreen].bounds.size.height - frame.size.width)/2;
y = ([UIScreen mainScreen].bounds.size.width - frame.size.height)/2;
}
return CGRectMake(x, y, frame.size.width, frame.size.height);
}

- (void)screenOrientationChanged {
// make blur view go away so that we can re-blur the original back
UIView *blurView = objc_getAssociatedObject(self, &CWBlurViewKey);
[UIView animateWithDuration:ANIMATION_TIME animations:^{
self.popupViewController.view.frame = [self getPopupFrameForViewController:self.popupViewController];
if (UIDeviceOrientationIsPortrait([UIDevice currentDevice].orientation)) {
blurView.frame = [UIScreen mainScreen].bounds;
} else {
blurView.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.height, [UIScreen mainScreen].bounds.size.width);
}
[UIView animateWithDuration:1.0f animations:^{
// for delay
} completion:^(BOOL finished) {
[blurView removeFromSuperview];
// popup view alpha to 0 so its not in the blur image
self.popupViewController.view.alpha = 0.0f;
[self addBlurView];
self.popupViewController.view.alpha = 1.0f;
// display blurView again
UIView *blurView = objc_getAssociatedObject(self, &CWBlurViewKey);
blurView.alpha = 1.0f;
}];
}];
}

#pragma mark - popupViewController getter/setter
Expand Down
12 changes: 12 additions & 0 deletions CWPopupDemo.xcodeproj/project.pbxproj
Expand Up @@ -8,6 +8,7 @@

/* Begin PBXBuildFile section */
CE2FCB9D17C72D1400359C70 /* UIViewController+CWPopup.m in Sources */ = {isa = PBXBuildFile; fileRef = CE2FCB9C17C72D1400359C70 /* UIViewController+CWPopup.m */; };
CE9AAD5417D8273100AFC34D /* mavericks.jpg in Resources */ = {isa = PBXBuildFile; fileRef = CE9AAD5317D8273000AFC34D /* mavericks.jpg */; };
CEE0779517C5BEB70012C196 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0779417C5BEB70012C196 /* Foundation.framework */; };
CEE0779717C5BEB70012C196 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0779617C5BEB70012C196 /* CoreGraphics.framework */; };
CEE0779917C5BEB70012C196 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0779817C5BEB70012C196 /* UIKit.framework */; };
Expand Down Expand Up @@ -40,6 +41,7 @@
/* Begin PBXFileReference section */
CE2FCB9B17C72D1400359C70 /* UIViewController+CWPopup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIViewController+CWPopup.h"; sourceTree = "<group>"; };
CE2FCB9C17C72D1400359C70 /* UIViewController+CWPopup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+CWPopup.m"; sourceTree = "<group>"; };
CE9AAD5317D8273000AFC34D /* mavericks.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = mavericks.jpg; sourceTree = "<group>"; };
CEE0779117C5BEB70012C196 /* CWPopupDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CWPopupDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
CEE0779417C5BEB70012C196 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
CEE0779617C5BEB70012C196 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
Expand Down Expand Up @@ -98,9 +100,18 @@
path = CWPopup;
sourceTree = "<group>";
};
CE9AAD5217D8272000AFC34D /* Images */ = {
isa = PBXGroup;
children = (
CE9AAD5317D8273000AFC34D /* mavericks.jpg */,
);
name = Images;
sourceTree = "<group>";
};
CEE0778817C5BEB70012C196 = {
isa = PBXGroup;
children = (
CE9AAD5217D8272000AFC34D /* Images */,
CE2FCB9A17C72D1400359C70 /* CWPopup */,
CEE0779C17C5BEB70012C196 /* CWPopupDemo */,
CEE0779317C5BEB70012C196 /* Frameworks */,
Expand Down Expand Up @@ -264,6 +275,7 @@
CEE077A117C5BEB70012C196 /* InfoPlist.strings in Resources */,
CEE077CF17C5BEDA0012C196 /* MainViewController.xib in Resources */,
CEE077AC17C5BEB70012C196 /* Images.xcassets in Resources */,
CE9AAD5417D8273100AFC34D /* mavericks.jpg in Resources */,
CEE077DA17C5BFF30012C196 /* SamplePopupViewController.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
1 change: 1 addition & 0 deletions CWPopupDemo/CWAppDelegate.m
Expand Up @@ -17,6 +17,7 @@ @implementation CWAppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[application setStatusBarStyle:UIStatusBarStyleLightContent];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
Expand Down
16 changes: 12 additions & 4 deletions CWPopupDemo/MainViewController.xib
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="4488.2" systemVersion="12E55" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
<dependencies>
<deployment defaultVersion="1280" identifier="iOS"/>
<deployment defaultVersion="1072" identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3715.3"/>
</dependencies>
<objects>
Expand All @@ -15,21 +15,29 @@
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="mavericks.jpg" id="PFg-40-svT">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
</imageView>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="QoT-3K-Hel">
<rect key="frame" x="109" y="269" width="102" height="30"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<state key="normal" title="Present Popup">
<color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<action selector="btnPresentPopup:" destination="-1" eventType="touchUpInside" id="jNZ-HW-NWI"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<simulatedStatusBarMetrics key="simulatedStatusBarMetrics"/>
<color key="backgroundColor" cocoaTouchSystemColor="lightTextColor"/>
<simulatedStatusBarMetrics key="simulatedStatusBarMetrics" statusBarStyle="lightContent"/>
<simulatedScreenMetrics key="simulatedDestinationMetrics" type="retina4"/>
</view>
</objects>
<resources>
<image name="mavericks.jpg" width="640" height="1136"/>
</resources>
</document>
5 changes: 5 additions & 0 deletions CWPopupDemo/SamplePopupViewController.m
Expand Up @@ -27,6 +27,11 @@ - (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
// use toolbar as background because its pretty in iOS7
UIToolbar *toolbarBackground = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 44, 200, 106)];
[self.view addSubview:toolbarBackground];
[self.view sendSubviewToBack:toolbarBackground];
// set size
}

- (void)didReceiveMemoryWarning
Expand Down
14 changes: 10 additions & 4 deletions CWPopupDemo/SamplePopupViewController.xib
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="4488.2" systemVersion="12E55" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
<dependencies>
<deployment defaultVersion="1280" identifier="iOS"/>
<deployment defaultVersion="1072" identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3715.3"/>
</dependencies>
<objects>
Expand All @@ -15,15 +15,21 @@
<rect key="frame" x="0.0" y="0.0" width="200" height="150"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="I'm a Popup!" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="ReR-Ke-ORz">
<rect key="frame" x="51" y="64" width="98" height="21"/>
<navigationBar contentMode="scaleToFill" id="Ja1-BT-MFA">
<rect key="frame" x="0.0" y="0.0" width="200" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<items>
<navigationItem title="I'm a Popup!" id="Lk9-or-1eq"/>
</items>
</navigationBar>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Something is happening..." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="S5m-zO-1VX">
<rect key="frame" x="20" y="69" width="160" height="51"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<simulatedStatusBarMetrics key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
</view>
Expand Down
Binary file added mavericks.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified screenshot.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 942999d

Please sign in to comment.