Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding a UIView contentView to the alert for generic usage #37

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 4 additions & 4 deletions SIAlertView/SIAlertView.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
Expand All @@ -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;
Expand Down
161 changes: 107 additions & 54 deletions SIAlertView/SIAlertView.m
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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];

Expand All @@ -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) = ^{
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -766,6 +816,7 @@ - (void)setup
[self setupContainerView];
[self updateTitleLabel];
[self updateMessageLabel];
[self updateContentView];
[self setupButtons];
[self invalidateLayout];
}
Expand All @@ -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;
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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