/Dependencies/KGModal/KGModal.m
Objective C | 432 lines | 336 code | 79 blank | 17 comment | 19 complexity | 3162980ac38b523cd7f7f8fdc122d125 MD5 | raw file
- //
- // KGModal.m
- // KGModal
- //
- // Created by David Keegan on 10/5/12.
- // Copyright (c) 2012 David Keegan. All rights reserved.
- //
- #import "KGModal.h"
- #import <QuartzCore/QuartzCore.h>
- CGFloat const kFadeInAnimationDuration = 0.3;
- CGFloat const kTransformPart1AnimationDuration = 0.2;
- CGFloat const kTransformPart2AnimationDuration = 0.1;
- CGFloat const kDefaultCloseButtonPadding = 17.0;
- NSString *const KGModalGradientViewTapped = @"KGModalGradientViewTapped";
- NSString *const KGModalWillShowNotification = @"KGModalWillShowNotification";
- NSString *const KGModalDidShowNotification = @"KGModalDidShowNotification";
- NSString *const KGModalWillHideNotification = @"KGModalWillHideNotification";
- NSString *const KGModalDidHideNotification = @"KGModalDidHideNotification";
- @interface KGModalGradientView : UIView
- @end
- @interface KGModalContainerView : UIView
- @property (weak, nonatomic) CALayer *styleLayer;
- @property (strong, nonatomic) UIColor *modalBackgroundColor;
- @end
- @interface KGModalCloseButton : UIButton
- @end
- @interface KGModalViewController : UIViewController
- @property (weak, nonatomic) KGModalGradientView *styleView;
- @end
- @interface KGModal()
- @property (strong, nonatomic) UIWindow *window;
- @property (strong, nonatomic) UIViewController *contentViewController;
- @property (weak, nonatomic) KGModalViewController *viewController;
- @property (weak, nonatomic) KGModalContainerView *containerView;
- @property (weak, nonatomic) KGModalCloseButton *closeButton;
- @property (weak, nonatomic) UIView *contentView;
- @end
- @implementation KGModal
- + (instancetype)sharedInstance{
- static id sharedInstance;
- static dispatch_once_t once;
- dispatch_once(&once, ^{
- sharedInstance = [[[self class] alloc] init];
- });
- return sharedInstance;
- }
- - (instancetype)init{
- if(!(self = [super init])){
- return nil;
- }
-
- self.shouldRotate = YES;
- self.tapOutsideToDismiss = YES;
- self.animateWhenDismissed = YES;
- self.closeButtonType = KGModalCloseButtonTypeLeft;
- self.modalBackgroundColor = [UIColor colorWithWhite:0 alpha:0.5];
-
- return self;
- }
- -(void)setCloseButtonType:(KGModalCloseButtonType)closeButtonType {
- _closeButtonType = closeButtonType;
- if(closeButtonType == KGModalCloseButtonTypeNone){
- [self.closeButton setHidden:YES];
- }else{
- [self.closeButton setHidden:NO];
-
- CGRect closeFrame = self.closeButton.frame;
- if(closeButtonType == KGModalCloseButtonTypeRight){
- closeFrame.origin.x = round(CGRectGetWidth(self.containerView.frame)-kDefaultCloseButtonPadding-CGRectGetWidth(closeFrame)/2);
- }else{
- closeFrame.origin.x = 0;
- }
- self.closeButton.frame = closeFrame;
- }
- }
- - (void)showWithContentView:(UIView *)contentView{
- [self showWithContentView:contentView andAnimated:YES];
- }
- - (void)showWithContentViewController:(UIViewController *)contentViewController{
- [self showWithContentViewController:contentViewController andAnimated:YES];
- }
- - (void)showWithContentViewController:(UIViewController *)contentViewController andAnimated:(BOOL)animated{
- self.contentViewController = contentViewController;
- [self showWithContentView:contentViewController.view andAnimated:YES];
- }
- - (void)showWithContentView:(UIView *)contentView andAnimated:(BOOL)animated {
- self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
- self.window.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
- self.window.opaque = NO;
-
- KGModalViewController *viewController = [[KGModalViewController alloc] init];
- self.window.rootViewController = viewController;
- self.viewController = viewController;
-
- CGFloat padding = 17;
- CGRect containerViewRect = CGRectInset(contentView.bounds, -padding, -padding);
- containerViewRect.origin.x = containerViewRect.origin.y = 0;
- containerViewRect.origin.x = round(CGRectGetMidX(self.window.bounds)-CGRectGetMidX(containerViewRect));
- containerViewRect.origin.y = round(CGRectGetMidY(self.window.bounds)-CGRectGetMidY(containerViewRect));
- KGModalContainerView *containerView = [[KGModalContainerView alloc] initWithFrame:containerViewRect];
- containerView.modalBackgroundColor = self.modalBackgroundColor;
- containerView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin|
- UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleBottomMargin;
- containerView.layer.rasterizationScale = [[UIScreen mainScreen] scale];
- contentView.frame = (CGRect){padding, padding, contentView.bounds.size};
- [containerView addSubview:contentView];
- [viewController.view addSubview:containerView];
- self.containerView = containerView;
-
- KGModalCloseButton *closeButton = [[KGModalCloseButton alloc] init];
-
- if(self.closeButtonType == KGModalCloseButtonTypeRight){
- CGRect closeFrame = closeButton.frame;
- closeFrame.origin.x = CGRectGetWidth(containerView.bounds)-CGRectGetWidth(closeFrame);
- closeButton.frame = closeFrame;
- }
-
- [closeButton addTarget:self action:@selector(closeAction:) forControlEvents:UIControlEventTouchUpInside];
- [containerView addSubview:closeButton];
- self.closeButton = closeButton;
-
- // Force adjust visibility and placing
- [self setCloseButtonType:self.closeButtonType];
-
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tapCloseAction:)
- name:KGModalGradientViewTapped object:nil];
-
- // The window has to be un-hidden on the main thread
- // This will cause the window to display
- dispatch_async(dispatch_get_main_queue(), ^{
- [[NSNotificationCenter defaultCenter] postNotificationName:KGModalWillShowNotification object:self];
- [self.window makeKeyAndVisible];
-
- if(animated){
- viewController.styleView.alpha = 0;
- [UIView animateWithDuration:kFadeInAnimationDuration animations:^{
- viewController.styleView.alpha = 1;
- }];
-
- containerView.alpha = 0;
- containerView.layer.shouldRasterize = YES;
- containerView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.4, 0.4);
- [UIView animateWithDuration:kTransformPart1AnimationDuration animations:^{
- containerView.alpha = 1;
- containerView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1.1, 1.1);
- } completion:^(BOOL finished) {
- [UIView animateWithDuration:kTransformPart2AnimationDuration delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
- containerView.alpha = 1;
- containerView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1, 1);
- } completion:^(BOOL finished2) {
- containerView.layer.shouldRasterize = NO;
- [[NSNotificationCenter defaultCenter] postNotificationName:KGModalDidShowNotification object:self];
- }];
- }];
- }
- });
- }
- - (void)closeAction:(id)sender{
- [self hideAnimated:self.animateWhenDismissed];
- }
- - (void)tapCloseAction:(id)sender{
- if(self.tapOutsideToDismiss){
- [self hideAnimated:self.animateWhenDismissed];
- }
- }
- - (void)hide{
- [self hideAnimated:YES];
- }
- - (void)hideWithCompletionBlock:(void(^)())completion{
- [self hideAnimated:YES withCompletionBlock:completion];
- }
- - (void)hideAnimated:(BOOL)animated{
- [self hideAnimated:animated withCompletionBlock:nil];
- }
- - (void)hideAnimated:(BOOL)animated withCompletionBlock:(void(^)())completion{
- if(!animated){
- [self cleanup];
- return;
- }
-
- dispatch_async(dispatch_get_main_queue(), ^{
- [[NSNotificationCenter defaultCenter] postNotificationName:KGModalWillHideNotification object:self];
- [UIView animateWithDuration:kFadeInAnimationDuration animations:^{
- self.viewController.styleView.alpha = 0;
- }];
-
- self.containerView.layer.shouldRasterize = YES;
- [UIView animateWithDuration:kTransformPart2AnimationDuration animations:^{
- self.containerView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1.1, 1.1);
- } completion:^(BOOL finished){
- [UIView animateWithDuration:kTransformPart1AnimationDuration delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
- self.containerView.alpha = 0;
- self.containerView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.4, 0.4);
- } completion:^(BOOL finished2){
- [self cleanup];
- if(completion){
- completion();
- }
- [[NSNotificationCenter defaultCenter] postNotificationName:KGModalDidHideNotification object:self];
- }];
- }];
- });
- }
- - (void)cleanup{
- [[NSNotificationCenter defaultCenter] removeObserver:self];
- [self.containerView removeFromSuperview];
- [[[[UIApplication sharedApplication] delegate] window] makeKeyWindow];
- [self.window removeFromSuperview];
- self.contentViewController = nil;
- self.window = nil;
- }
- - (void)setModalBackgroundColor:(UIColor *)modalBackgroundColor{
- if(_modalBackgroundColor != modalBackgroundColor){
- _modalBackgroundColor = modalBackgroundColor;
- self.containerView.modalBackgroundColor = modalBackgroundColor;
- }
- }
- - (void)dealloc{
- [self cleanup];
- }
- @end
- @implementation KGModalViewController
- - (void)loadView{
- self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
- }
- - (void)viewDidLoad{
- [super viewDidLoad];
-
- self.view.backgroundColor = [UIColor clearColor];
- self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
-
- KGModalGradientView *styleView = [[KGModalGradientView alloc] initWithFrame:self.view.bounds];
- styleView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
- styleView.opaque = NO;
- [self.view addSubview:styleView];
- self.styleView = styleView;
- }
- - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
- return [[KGModal sharedInstance] shouldRotate];
- }
- - (BOOL)shouldAutorotate{
- return [[KGModal sharedInstance] shouldRotate];
- }
- @end
- @implementation KGModalContainerView
- - (instancetype)initWithFrame:(CGRect)frame{
- if(!(self = [super initWithFrame:frame])){
- return nil;
- }
-
- CALayer *styleLayer = [[CALayer alloc] init];
- styleLayer.cornerRadius = 4;
- styleLayer.shadowColor= [[UIColor blackColor] CGColor];
- styleLayer.shadowOffset = CGSizeMake(0, 0);
- styleLayer.shadowOpacity = 0.5;
- styleLayer.borderWidth = 1;
- styleLayer.borderColor = [[UIColor whiteColor] CGColor];
- styleLayer.frame = CGRectInset(self.bounds, 12, 12);
- [self.layer addSublayer:styleLayer];
- self.styleLayer = styleLayer;
-
- return self;
- }
- - (void)setModalBackgroundColor:(UIColor *)modalBackgroundColor{
- if(_modalBackgroundColor != modalBackgroundColor){
- _modalBackgroundColor = modalBackgroundColor;
- self.styleLayer.backgroundColor = [modalBackgroundColor CGColor];
- }
- }
- @end
- @implementation KGModalGradientView
- - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
- [[NSNotificationCenter defaultCenter] postNotificationName:KGModalGradientViewTapped object:nil];
- }
- - (void)drawRect:(CGRect)rect{
- CGContextRef context = UIGraphicsGetCurrentContext();
- if([[KGModal sharedInstance] backgroundDisplayStyle] == KGModalBackgroundDisplayStyleSolid){
- [[UIColor colorWithWhite:0 alpha:0.55] set];
- CGContextFillRect(context, self.bounds);
- }else{
- CGContextSaveGState(context);
- size_t gradLocationsNum = 2;
- CGFloat gradLocations[2] = {0.0f, 1.0f};
- CGFloat gradColors[8] = {0, 0, 0, 0.3, 0, 0, 0, 0.8};
- CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
- CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, gradColors, gradLocations, gradLocationsNum);
- CGColorSpaceRelease(colorSpace), colorSpace = NULL;
- CGPoint gradCenter= CGPointMake(round(CGRectGetMidX(self.bounds)), round(CGRectGetMidY(self.bounds)));
- CGFloat gradRadius = MAX(CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds));
- CGContextDrawRadialGradient(context, gradient, gradCenter, 0, gradCenter, gradRadius, kCGGradientDrawsAfterEndLocation);
- CGGradientRelease(gradient), gradient = NULL;
- CGContextRestoreGState(context);
- }
- }
- @end
- @implementation KGModalCloseButton
- - (instancetype)init
- {
- if(!(self = [super initWithFrame:(CGRect){0, 0, 32, 32}]))
- {
- return nil;
- }
- static UIImage *closeButtonImage;
- static dispatch_once_t once;
- dispatch_once(&once, ^{
- closeButtonImage = [self closeButtonImage];
- });
- [self setBackgroundImage:closeButtonImage forState:UIControlStateNormal];
- return self;
- }
- - (UIImage *)closeButtonImage
- {
- UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0);
-
- //// General Declarations
- CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
- CGContextRef context = UIGraphicsGetCurrentContext();
-
- //// Color Declarations
- UIColor *topGradient = [UIColor colorWithRed:0.21 green:0.21 blue:0.21 alpha:0.9];
- UIColor *bottomGradient = [UIColor colorWithRed:0.03 green:0.03 blue:0.03 alpha:0.9];
-
- //// Gradient Declarations
- NSArray *gradientColors = @[(id)topGradient.CGColor,
- (id)bottomGradient.CGColor];
- CGFloat gradientLocations[] = {0, 1};
- CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)gradientColors, gradientLocations);
-
- //// Shadow Declarations
- CGColorRef shadow = [UIColor blackColor].CGColor;
- CGSize shadowOffset = CGSizeMake(0, 1);
- CGFloat shadowBlurRadius = 3;
- CGColorRef shadow2 = [UIColor blackColor].CGColor;
- CGSize shadow2Offset = CGSizeMake(0, 1);
- CGFloat shadow2BlurRadius = 0;
-
-
- //// Oval Drawing
- UIBezierPath *ovalPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(4, 3, 24, 24)];
- CGContextSaveGState(context);
- [ovalPath addClip];
- CGContextDrawLinearGradient(context, gradient, CGPointMake(16, 3), CGPointMake(16, 27), 0);
- CGContextRestoreGState(context);
-
- CGContextSaveGState(context);
- CGContextSetShadowWithColor(context, shadowOffset, shadowBlurRadius, shadow);
- [[UIColor whiteColor] setStroke];
- ovalPath.lineWidth = 2;
- [ovalPath stroke];
- CGContextRestoreGState(context);
-
-
- //// Bezier Drawing
- UIBezierPath *bezierPath = [UIBezierPath bezierPath];
- [bezierPath moveToPoint:CGPointMake(22.36, 11.46)];
- [bezierPath addLineToPoint:CGPointMake(18.83, 15)];
- [bezierPath addLineToPoint:CGPointMake(22.36, 18.54)];
- [bezierPath addLineToPoint:CGPointMake(19.54, 21.36)];
- [bezierPath addLineToPoint:CGPointMake(16, 17.83)];
- [bezierPath addLineToPoint:CGPointMake(12.46, 21.36)];
- [bezierPath addLineToPoint:CGPointMake(9.64, 18.54)];
- [bezierPath addLineToPoint:CGPointMake(13.17, 15)];
- [bezierPath addLineToPoint:CGPointMake(9.64, 11.46)];
- [bezierPath addLineToPoint:CGPointMake(12.46, 8.64)];
- [bezierPath addLineToPoint:CGPointMake(16, 12.17)];
- [bezierPath addLineToPoint:CGPointMake(19.54, 8.64)];
- [bezierPath addLineToPoint:CGPointMake(22.36, 11.46)];
- [bezierPath closePath];
- CGContextSaveGState(context);
- CGContextSetShadowWithColor(context, shadow2Offset, shadow2BlurRadius, shadow2);
- [[UIColor whiteColor] setFill];
- [bezierPath fill];
- CGContextRestoreGState(context);
-
-
- //// Cleanup
- CGGradientRelease(gradient);
- CGColorSpaceRelease(colorSpace);
-
- UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
- UIGraphicsEndImageContext();
-
- return image;
- }
- @end