diff --git a/SIAlertView/SIAlertView.h b/SIAlertView/SIAlertView.h index 156c676..138ef0e 100644 --- a/SIAlertView/SIAlertView.h +++ b/SIAlertView/SIAlertView.h @@ -39,6 +39,7 @@ typedef void(^SIAlertViewHandler)(SIAlertView *alertView); @property (nonatomic, copy) NSString *title; @property (nonatomic, copy) NSString *message; +@property (nonatomic, strong) UIView *contentView; @property (nonatomic, assign) SIAlertViewTransitionStyle transitionStyle; // default is SIAlertViewTransitionStyleSlideFromBottom @property (nonatomic, assign) SIAlertViewBackgroundStyle backgroundStyle; // default is SIAlertViewButtonTypeGradient @@ -50,6 +51,8 @@ typedef void(^SIAlertViewHandler)(SIAlertView *alertView); @property (nonatomic, readonly, getter = isVisible) BOOL visible; +@property (nonatomic, readonly, getter = isParallaxEffectEnabled) BOOL enabledParallaxEffect; + @property (nonatomic, strong) UIColor *viewBackgroundColor NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; @property (nonatomic, strong) UIColor *titleColor NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; @property (nonatomic, strong) UIColor *messageColor NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; @@ -62,11 +65,8 @@ typedef void(^SIAlertViewHandler)(SIAlertView *alertView); @property (nonatomic, assign) CGFloat cornerRadius NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; // default is 2.0 @property (nonatomic, assign) CGFloat shadowRadius NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; // default is 8.0 -- (void)setDefaultButtonImage:(UIImage *)defaultButtonImage forState:(UIControlState)state NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; -- (void)setCancelButtonImage:(UIImage *)cancelButtonImage forState:(UIControlState)state NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; -- (void)setDestructiveButtonImage:(UIImage *)destructiveButtonImage forState:(UIControlState)state NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR; - - (id)initWithTitle:(NSString *)title andMessage:(NSString *)message; +- (id)initWithTitle:(NSString *)title andMessage:(NSString *)message andContentView:(UIView *)contentView; - (void)addButtonWithTitle:(NSString *)title type:(SIAlertViewButtonType)type handler:(SIAlertViewHandler)handler; - (void)show; diff --git a/SIAlertView/SIAlertView.m b/SIAlertView/SIAlertView.m index 7895934..bcbe09a 100644 --- a/SIAlertView/SIAlertView.m +++ b/SIAlertView/SIAlertView.m @@ -24,7 +24,7 @@ #define CONTENT_PADDING_TOP 12 #define CONTENT_PADDING_BOTTOM 10 #define BUTTON_HEIGHT 44 -#define CONTAINER_WIDTH 300 +#define CONTAINER_WIDTH 290 const UIWindowLevel UIWindowLevelSIAlert = 1999.0; // don't overlap system's alert const UIWindowLevel UIWindowLevelSIAlertBackground = 1998.0; // below the alert window @@ -215,11 +215,21 @@ - (id)initWithTitle:(NSString *)title andMessage:(NSString *)message if (self) { _title = title; _message = message; + _enabledParallaxEffect = YES; self.items = [[NSMutableArray alloc] init]; } return self; } +- (id)initWithTitle:(NSString *)title andMessage:(NSString *)message andContentView:(UIView *)contentView +{ + self = [self initWithTitle:title andMessage:message]; + if (self) { + _contentView = contentView; + } + return self; +} + #pragma mark - Class methods + (NSMutableArray *)sharedQueue @@ -295,6 +305,12 @@ - (void)setMessage:(NSString *)message [self invalidateLayout]; } +- (void)setContentView:(UIView *)contentView +{ + _containerView = contentView; + [self invalidateLayout]; +} + #pragma mark - Public - (void)addButtonWithTitle:(NSString *)title type:(SIAlertViewButtonType)type handler:(SIAlertViewHandler)handler @@ -361,6 +377,9 @@ - (void)show self.didShowHandler(self); } [[NSNotificationCenter defaultCenter] postNotificationName:SIAlertViewDidShowNotification object:self userInfo:nil]; + #ifdef __IPHONE_7_0 + [self addParallaxEffect]; + #endif [SIAlertView setAnimating:NO]; @@ -385,6 +404,9 @@ - (void)dismissAnimated:(BOOL)animated cleanup:(BOOL)cleanup self.willDismissHandler(self); } [[NSNotificationCenter defaultCenter] postNotificationName:SIAlertViewWillDismissNotification object:self userInfo:nil]; + #ifdef __IPHONE_7_0 + [self removeParallaxEffect]; + #endif } void (^dismissComplete)(void) = ^{ @@ -657,7 +679,19 @@ - (void)validateLayout self.containerView.layer.shadowPath = [UIBezierPath bezierPathWithRoundedRect:self.containerView.bounds cornerRadius:self.containerView.layer.cornerRadius].CGPath; CGFloat y = CONTENT_PADDING_TOP; + if (self.contentView) { + if (y > CONTENT_PADDING_TOP) { + y += GAP; + } + CGFloat height = self.contentView.bounds.size.height; + self.contentView.frame = CGRectMake(CONTENT_PADDING_LEFT, y, self.containerView.bounds.size.width - CONTENT_PADDING_LEFT * 2, height); + y += height; + } + if (self.titleLabel) { + if (y > CONTENT_PADDING_TOP) { + y += GAP; + } self.titleLabel.text = self.title; CGFloat height = [self heightForTitleLabel]; self.titleLabel.frame = CGRectMake(CONTENT_PADDING_LEFT, y, self.containerView.bounds.size.width - CONTENT_PADDING_LEFT * 2, height); @@ -711,6 +745,12 @@ - (CGFloat)preferredHeight } height += [self heightForMessageLabel]; } + if (self.contentView) { + if (height > CONTENT_PADDING_TOP) { + height += GAP; + } + height += self.contentView.frame.size.height; + } if (self.items.count > 0) { if (height > CONTENT_PADDING_TOP) { height += GAP; @@ -725,23 +765,25 @@ - (CGFloat)preferredHeight } } height += CONTENT_PADDING_BOTTOM; + return height; } - (CGFloat)heightForTitleLabel { if (self.titleLabel) { - CGSize size = [self.title sizeWithFont:self.titleLabel.font - minFontSize: -#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_6_0 - self.titleLabel.font.pointSize * self.titleLabel.minimumScaleFactor -#else - self.titleLabel.minimumFontSize -#endif - actualFontSize:nil - forWidth:CONTAINER_WIDTH - CONTENT_PADDING_LEFT * 2 - lineBreakMode:self.titleLabel.lineBreakMode]; - return size.height; + + UIFont *font = self.titleLabel.font; + + CGFloat constrainedHeight = font.lineHeight; + + NSDictionary *fontAtts = @{NSFontAttributeName : font}; + + CGRect rect = [self.title boundingRectWithSize:CGSizeMake(CONTAINER_WIDTH - CONTENT_PADDING_LEFT * 2, constrainedHeight) + options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesLineFragmentOrigin + attributes:fontAtts + context:nil]; + return rect.size.height; } return 0; } @@ -750,11 +792,19 @@ - (CGFloat)heightForMessageLabel { CGFloat minHeight = MESSAGE_MIN_LINE_COUNT * self.messageLabel.font.lineHeight; if (self.messageLabel) { - CGFloat maxHeight = MESSAGE_MAX_LINE_COUNT * self.messageLabel.font.lineHeight; - CGSize size = [self.message sizeWithFont:self.messageLabel.font - constrainedToSize:CGSizeMake(CONTAINER_WIDTH - CONTENT_PADDING_LEFT * 2, maxHeight) - lineBreakMode:self.messageLabel.lineBreakMode]; - return MAX(minHeight, size.height); + + UIFont *font = self.messageLabel.font; + + CGFloat maxHeight = MESSAGE_MAX_LINE_COUNT * font.lineHeight; + + NSDictionary *fontAtts = @{NSFontAttributeName : font}; + + CGRect rect = [self.title boundingRectWithSize:CGSizeMake(CONTAINER_WIDTH - CONTENT_PADDING_LEFT * 2, maxHeight) + options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesLineFragmentOrigin + attributes:fontAtts + context:nil]; + + return MAX(minHeight, rect.size.height); } return minHeight; } @@ -766,6 +816,7 @@ - (void)setup [self setupContainerView]; [self updateTitleLabel]; [self updateMessageLabel]; + [self updateContentView]; [self setupButtons]; [self invalidateLayout]; } @@ -776,6 +827,7 @@ - (void)teardown self.containerView = nil; self.titleLabel = nil; self.messageLabel = nil; + self.contentView = nil; [self.buttons removeAllObjects]; [self.alertWindow removeFromSuperview]; self.alertWindow = nil; @@ -803,11 +855,7 @@ - (void)updateTitleLabel self.titleLabel.font = self.titleFont; self.titleLabel.textColor = self.titleColor; self.titleLabel.adjustsFontSizeToFitWidth = YES; -#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_6_0 self.titleLabel.minimumScaleFactor = 0.75; -#else - self.titleLabel.minimumFontSize = self.titleLabel.font.pointSize * 0.75; -#endif [self.containerView addSubview:self.titleLabel]; #if DEBUG_LAYOUT self.titleLabel.backgroundColor = [UIColor redColor]; @@ -844,6 +892,14 @@ - (void)updateMessageLabel [self invalidateLayout]; } +- (void)updateContentView +{ + if (self.contentView) { + [self.containerView addSubview:self.contentView]; + } + [self invalidateLayout]; +} + - (void)setupButtons { self.buttons = [[NSMutableArray alloc] initWithCapacity:self.items.count]; @@ -1024,48 +1080,45 @@ - (void)setDestructiveButtonColor:(UIColor *)buttonColor [self setColor:buttonColor toButtonsOfType:SIAlertViewButtonTypeDestructive]; } - -- (void)setDefaultButtonImage:(UIImage *)defaultButtonImage forState:(UIControlState)state -{ - [self setButtonImage:defaultButtonImage forState:state andButtonType:SIAlertViewButtonTypeDefault]; -} - - -- (void)setCancelButtonImage:(UIImage *)cancelButtonImage forState:(UIControlState)state -{ - [self setButtonImage:cancelButtonImage forState:state andButtonType:SIAlertViewButtonTypeCancel]; -} - - -- (void)setDestructiveButtonImage:(UIImage *)destructiveButtonImage forState:(UIControlState)state -{ - [self setButtonImage:destructiveButtonImage forState:state andButtonType:SIAlertViewButtonTypeDestructive]; +- (void)setColor:(UIColor *)color toButtonsOfType:(SIAlertViewButtonType)type { + for (NSUInteger i = 0; i < self.items.count; i++) { + SIAlertItem *item = self.items[i]; + if(item.type == type) { + UIButton *button = self.buttons[i]; + [button setTitleColor:color forState:UIControlStateNormal]; + [button setTitleColor:[color colorWithAlphaComponent:0.8] forState:UIControlStateHighlighted]; + } + } } +# pragma mark - +# pragma mark Enable parallax effect (iOS7 only) -- (void)setButtonImage:(UIImage *)image forState:(UIControlState)state andButtonType:(SIAlertViewButtonType)type +#ifdef __IPHONE_7_0 +- (void)addParallaxEffect { - for (NSUInteger i = 0; i < self.items.count; i++) + if (_enabledParallaxEffect && NSClassFromString(@"UIInterpolatingMotionEffect")) { - SIAlertItem *item = self.items[i]; - if(item.type == type) - { - UIButton *button = self.buttons[i]; - [button setBackgroundImage:image forState:state]; - } + UIInterpolatingMotionEffect *effectHorizontal = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"position.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis]; + UIInterpolatingMotionEffect *effectVertical = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"position.y" type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis]; + [effectHorizontal setMaximumRelativeValue:@(10.0f)]; + [effectHorizontal setMinimumRelativeValue:@(-10.0f)]; + [effectVertical setMaximumRelativeValue:@(20.0f)]; + [effectVertical setMinimumRelativeValue:@(-20.0f)]; + [self.containerView addMotionEffect:effectHorizontal]; + [self.containerView addMotionEffect:effectVertical]; } } - --(void)setColor:(UIColor *)color toButtonsOfType:(SIAlertViewButtonType)type { - for (NSUInteger i = 0; i < self.items.count; i++) { - SIAlertItem *item = self.items[i]; - if(item.type == type) { - UIButton *button = self.buttons[i]; - [button setTitleColor:color forState:UIControlStateNormal]; - [button setTitleColor:[color colorWithAlphaComponent:0.8] forState:UIControlStateHighlighted]; - } +- (void)removeParallaxEffect +{ + if (_enabledParallaxEffect && NSClassFromString(@"UIInterpolatingMotionEffect")) + { + [self.containerView.motionEffects enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + [self.containerView removeMotionEffect:obj]; + }]; } } +#endif @end