diff --git a/NoticeView.xcodeproj/project.pbxproj b/NoticeView.xcodeproj/project.pbxproj index 9eccb9a..0937a40 100644 --- a/NoticeView.xcodeproj/project.pbxproj +++ b/NoticeView.xcodeproj/project.pbxproj @@ -25,6 +25,8 @@ 746CBCFC15709E8300B844B1 /* WBBaseNoticeView.m in Sources */ = {isa = PBXBuildFile; fileRef = 746CBCFB15709E8300B844B1 /* WBBaseNoticeView.m */; }; 746CBD001570A1D100B844B1 /* WBErrorNoticeView.m in Sources */ = {isa = PBXBuildFile; fileRef = 746CBCFF1570A1D100B844B1 /* WBErrorNoticeView.m */; }; 746CBD081570A8FA00B844B1 /* WBSuccessNoticeView.m in Sources */ = {isa = PBXBuildFile; fileRef = 746CBD071570A8FA00B844B1 /* WBSuccessNoticeView.m */; }; + 748A6A59157D0B74003C7655 /* WBGrayGradientView.m in Sources */ = {isa = PBXBuildFile; fileRef = 748A6A58157D0B74003C7655 /* WBGrayGradientView.m */; }; + 748A6A5D157D0D06003C7655 /* WBStickyNoticeView.m in Sources */ = {isa = PBXBuildFile; fileRef = 748A6A5C157D0D06003C7655 /* WBStickyNoticeView.m */; }; 7492FA45157C8CD700FB834C /* WBBlueGradientView.m in Sources */ = {isa = PBXBuildFile; fileRef = 7492FA42157C8CD700FB834C /* WBBlueGradientView.m */; }; 7492FA46157C8CD700FB834C /* WBRedGradientView.m in Sources */ = {isa = PBXBuildFile; fileRef = 7492FA44157C8CD700FB834C /* WBRedGradientView.m */; }; /* End PBXBuildFile section */ @@ -59,6 +61,10 @@ 746CBD011570A65D00B844B1 /* WBNoticeView_Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WBNoticeView_Private.h; sourceTree = ""; }; 746CBD061570A8FA00B844B1 /* WBSuccessNoticeView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WBSuccessNoticeView.h; sourceTree = ""; }; 746CBD071570A8FA00B844B1 /* WBSuccessNoticeView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WBSuccessNoticeView.m; sourceTree = ""; }; + 748A6A57157D0B74003C7655 /* WBGrayGradientView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WBGrayGradientView.h; sourceTree = ""; }; + 748A6A58157D0B74003C7655 /* WBGrayGradientView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WBGrayGradientView.m; sourceTree = ""; }; + 748A6A5B157D0D06003C7655 /* WBStickyNoticeView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WBStickyNoticeView.h; sourceTree = ""; }; + 748A6A5C157D0D06003C7655 /* WBStickyNoticeView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WBStickyNoticeView.m; sourceTree = ""; }; 7492FA41157C8CD700FB834C /* WBBlueGradientView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WBBlueGradientView.h; sourceTree = ""; }; 7492FA42157C8CD700FB834C /* WBBlueGradientView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WBBlueGradientView.m; sourceTree = ""; }; 7492FA43157C8CD700FB834C /* WBRedGradientView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WBRedGradientView.h; sourceTree = ""; }; @@ -97,6 +103,8 @@ 746CBCFF1570A1D100B844B1 /* WBErrorNoticeView.m */, 746CBD061570A8FA00B844B1 /* WBSuccessNoticeView.h */, 746CBD071570A8FA00B844B1 /* WBSuccessNoticeView.m */, + 748A6A5B157D0D06003C7655 /* WBStickyNoticeView.h */, + 748A6A5C157D0D06003C7655 /* WBStickyNoticeView.m */, 746CBD051570A88800B844B1 /* Private */, ); path = WBNoticeView; @@ -169,6 +177,8 @@ 592BDDE615645BEE00B78820 /* UILabel+WBExtensions.m */, 7492FA41157C8CD700FB834C /* WBBlueGradientView.h */, 7492FA42157C8CD700FB834C /* WBBlueGradientView.m */, + 748A6A57157D0B74003C7655 /* WBGrayGradientView.h */, + 748A6A58157D0B74003C7655 /* WBGrayGradientView.m */, 7492FA43157C8CD700FB834C /* WBRedGradientView.h */, 7492FA44157C8CD700FB834C /* WBRedGradientView.m */, ); @@ -253,6 +263,8 @@ 746CBD081570A8FA00B844B1 /* WBSuccessNoticeView.m in Sources */, 7492FA45157C8CD700FB834C /* WBBlueGradientView.m in Sources */, 7492FA46157C8CD700FB834C /* WBRedGradientView.m in Sources */, + 748A6A59157D0B74003C7655 /* WBGrayGradientView.m in Sources */, + 748A6A5D157D0D06003C7655 /* WBStickyNoticeView.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/NoticeView/WBNoticeView/NoticeView.bundle/up.png b/NoticeView/WBNoticeView/NoticeView.bundle/up.png new file mode 100755 index 0000000..5f18a56 Binary files /dev/null and b/NoticeView/WBNoticeView/NoticeView.bundle/up.png differ diff --git a/NoticeView/WBNoticeView/WBGrayGradientView.h b/NoticeView/WBNoticeView/WBGrayGradientView.h new file mode 100644 index 0000000..4000aee --- /dev/null +++ b/NoticeView/WBNoticeView/WBGrayGradientView.h @@ -0,0 +1,13 @@ +// +// WBGrayGradientView.h +// GradientView +// +// Created by Tito Ciuro on 6/3/12. +// Copyright (c) 2012 Webbo, LLC. All rights reserved. +// + +#import + +@interface WBGrayGradientView : UIView + +@end diff --git a/NoticeView/WBNoticeView/WBGrayGradientView.m b/NoticeView/WBNoticeView/WBGrayGradientView.m new file mode 100644 index 0000000..3673fd3 --- /dev/null +++ b/NoticeView/WBNoticeView/WBGrayGradientView.m @@ -0,0 +1,42 @@ +// +// WBGrayGradientView.m +// GradientView +// +// Created by Tito Ciuro on 6/3/12. +// Copyright (c) 2012 Webbo, LLC. All rights reserved. +// + +#import + +#import "WBGrayGradientView.h" + +@implementation WBGrayGradientView + +- (void)drawRect:(CGRect)rect +{ + UIColor *redTop = [UIColor colorWithRed:198/255.0f green:200/255.0f blue:202/255.0f alpha:1.0]; + UIColor *redBot = [UIColor colorWithRed:225/255.0f green:228/255.0f blue:229/255.0f alpha:1.0]; + + CAGradientLayer *gradient = [CAGradientLayer layer]; + gradient.frame = self.bounds; + gradient.colors = [NSArray arrayWithObjects: + (id)redTop.CGColor, + (id)redBot.CGColor, + nil]; + gradient.locations = [NSArray arrayWithObjects: + [NSNumber numberWithFloat:0.0f], + [NSNumber numberWithFloat:0.7], + nil]; + + [self.layer insertSublayer:gradient atIndex:0]; + + UIView *firstBotWhiteLine = [[UIView alloc]initWithFrame:CGRectMake(0.0, self.bounds.size.height - 1, self.frame.size.width, 1.0)]; + firstBotWhiteLine.backgroundColor = [UIColor colorWithRed:236/255.0f green:238/255.0f blue:239/255.0f alpha:1.0]; + [self addSubview:firstBotWhiteLine]; + + UIView *secondBotDarkLine = [[UIView alloc]initWithFrame:CGRectMake(0.0, self.bounds.size.height, self.frame.size.width, 1.0)]; + secondBotDarkLine.backgroundColor = [UIColor colorWithRed:113/255.0f green:114/255.0f blue:115/255.0f alpha:1.0]; + [self addSubview:secondBotDarkLine]; +} + +@end diff --git a/NoticeView/WBNoticeView/WBNoticeView.h b/NoticeView/WBNoticeView/WBNoticeView.h index 05662c7..ffe5a54 100644 --- a/NoticeView/WBNoticeView/WBNoticeView.h +++ b/NoticeView/WBNoticeView/WBNoticeView.h @@ -12,7 +12,8 @@ typedef enum { WBNoticeViewTypeError = 0, - WBNoticeViewTypeSuccess + WBNoticeViewTypeSuccess, + WBNoticeViewTypeSticky } WBNoticeViewType; + (WBNoticeView *)defaultManager; @@ -50,4 +51,12 @@ typedef enum { alpha:(float)alpha yOrigin:(CGFloat)origin; +// Sticky notice methods + +- (void)showStickyNoticeInView:(UIView *)view + message:(NSString *)message + duration:(float)duration + alpha:(float)alpha + yOrigin:(CGFloat)origin; + @end diff --git a/NoticeView/WBNoticeView/WBNoticeView.m b/NoticeView/WBNoticeView/WBNoticeView.m index e67641f..ac081b3 100644 --- a/NoticeView/WBNoticeView/WBNoticeView.m +++ b/NoticeView/WBNoticeView/WBNoticeView.m @@ -10,6 +10,7 @@ #import "WBNoticeView_Private.h" #import "WBRedGradientView.h" #import "WBBlueGradientView.h" +#import "WBGrayGradientView.h" #import "UILabel+WBExtensions.h" #import @@ -20,6 +21,48 @@ @property(nonatomic, strong) UILabel *titleLabel; @property(nonatomic, strong) UILabel *messageLabel; +@property(nonatomic, assign) CGFloat _duration; +@property(nonatomic, assign) CGFloat _delay; +@property(nonatomic, assign) CGFloat _alpha; +@property(nonatomic, assign) CGFloat _hiddenYOrigin; +@property(nonatomic, strong) WBNoticeView *_currentNotice; + +- (void)_showErrorNoticeInView:(UIView *)view + title:(NSString *)title + message:(NSString *)message + duration:(float)duration + delay:(float)delay + alpha:(float)alpha + yOrigin:(CGFloat)origin; + +- (void)_showSuccessNoticeInView:(UIView *)view + title:(NSString *)title + message:(NSString *)message + duration:(float)duration + delay:(float)delay + alpha:(float)alpha + yOrigin:(CGFloat)origin; + +- (void)_showStickyNoticeInView:(UIView *)view + title:(NSString *)title + message:(NSString *)message + duration:(float)duration + delay:(float)delay + alpha:(float)alpha + yOrigin:(CGFloat)origin; + +- (void)displayNoticeOfType:(WBNoticeViewType)noticeType + duration:(CGFloat)duration + delay:(CGFloat)delay + origin:(CGFloat)origin + hiddenYOrigin:(CGFloat)hiddenYOrigin + alpha:(CGFloat)alpha; + +- (void)dismissNoticeOfType:(WBNoticeViewType)noticeType + duration:(CGFloat)duration + delay:(CGFloat)delay + hiddenYOrigin:(CGFloat)hiddenYOrigin; + - (void)cleanup; @end @@ -27,6 +70,11 @@ @implementation WBNoticeView @synthesize noticeView, titleLabel, messageLabel; +@synthesize _duration; +@synthesize _delay; +@synthesize _alpha; +@synthesize _hiddenYOrigin; +@synthesize _currentNotice; + (WBNoticeView *)defaultManager { @@ -90,6 +138,8 @@ yOrigin:origin]; } +#pragma mark - + - (void)showSuccessNoticeInView:(UIView *)view message:(NSString *)message { @@ -136,6 +186,24 @@ yOrigin:origin]; } +#pragma mark - + +- (void)showStickyNoticeInView:(UIView *)view + message:(NSString *)message + duration:(float)duration + alpha:(float)alpha + yOrigin:(CGFloat)origin +{ + [self _showNoticeOfType:WBNoticeViewTypeSticky + view:view + title:message + message:nil + duration:duration + delay:0.0 + alpha:alpha + yOrigin:origin]; +} + #pragma mark - Private Section - (void)_showNoticeOfType:(WBNoticeViewType)noticeType @@ -148,127 +216,336 @@ yOrigin:(CGFloat)origin { if (nil == self.noticeView) { + // Set default values if needed if (nil == title) title = @"Unknown Error"; if (nil == message) message = @"Information not provided."; if (0.0 == duration) duration = 0.5; - if (0.0 == delay) delay = 2.0; + if ((0.0 == delay) && (WBNoticeViewTypeSticky != noticeType)) delay = 2.0; if (0.0 == alpha) alpha = 1.0; if (origin < 0.0) origin = 0.0; - - // Obtain the screen width - CGFloat viewWidth = view.frame.size.width; - // Locate the images - NSString *path = [[[NSBundle mainBundle]resourcePath]stringByAppendingPathComponent:@"NoticeView.bundle"]; - NSString *noticeIconImageName = [path stringByAppendingPathComponent:(WBNoticeViewTypeError == noticeType ? @"notice_error_icon.png" : @"notice_success_icon.png")]; - NSInteger numberOfLines = 1; - CGFloat messageLineHeight = 30.0; - - // Make and add the title label - float titleYOrigin = (WBNoticeViewTypeError == noticeType ? 10.0 : 18.0); - self.titleLabel = [[UILabel alloc]initWithFrame:CGRectMake(55.0, titleYOrigin, viewWidth - 70.0, 16.0)]; - self.titleLabel.font = [UIFont boldSystemFontOfSize:14.0]; - self.titleLabel.textColor = [UIColor whiteColor]; - self.titleLabel.backgroundColor = [UIColor clearColor]; - self.titleLabel.shadowOffset = CGSizeMake(0.0, -1.0); - self.titleLabel.shadowColor = [UIColor blackColor]; - self.titleLabel.text = title; - - if (WBNoticeViewTypeError == noticeType) { - // Make the message label - self.messageLabel = [[UILabel alloc]initWithFrame:CGRectMake(55.0, 10.0 + 10.0, viewWidth - 70.0, messageLineHeight)]; - self.messageLabel.font = [UIFont systemFontOfSize:13.0]; - self.messageLabel.textColor = [UIColor colorWithRed:239.0/255.0 green:167.0/255.0 blue:163.0/255.0 alpha:1.0]; - self.messageLabel.backgroundColor = [UIColor clearColor]; - self.messageLabel.text = message; - - // Calculate the number of lines it'll take to display the text - numberOfLines = [[self.messageLabel lines]count]; - self.messageLabel.numberOfLines = numberOfLines; - CGRect r = self.messageLabel.frame; - r.origin.y = self.titleLabel.frame.origin.y + self.titleLabel.frame.size.height;//(1 == numberOfLines) ? self.titleLabel.frame.origin.y : self.titleLabel.frame.origin.y - 11.0; - - // This step is needed to avoid having the UILabel center the text in the middle - [self.messageLabel sizeToFit]; - - // Now we can determine the height of one line of text - messageLineHeight = self.messageLabel.frame.size.height; - r.size.height = self.messageLabel.frame.size.height * numberOfLines; - r.size.width = viewWidth - 70.0; - self.messageLabel.frame = r; + switch (noticeType) { + case WBNoticeViewTypeError: + [self _showErrorNoticeInView:view title:title message:message duration:duration delay:delay alpha:alpha yOrigin:origin]; + break; + + case WBNoticeViewTypeSuccess: + [self _showSuccessNoticeInView:view title:title message:message duration:duration delay:delay alpha:alpha yOrigin:origin]; + break; + + case WBNoticeViewTypeSticky: + [self _showStickyNoticeInView:view title:title message:message duration:duration delay:delay alpha:alpha yOrigin:origin]; + break; } - - // Calculate the notice view height - float noticeViewHeight = (WBNoticeViewTypeError == noticeType ? 50.0 : 40.0); - float hiddenYOrigin = 0.0; - if (numberOfLines > 1) { - noticeViewHeight += (numberOfLines - 1) * messageLineHeight; - } - - // Make sure we hide completely the view, including its shadow - hiddenYOrigin = -noticeViewHeight - 20.0; - - // Make and add the notice view - if (WBNoticeViewTypeError == noticeType) { - self.noticeView = [[WBRedGradientView alloc]initWithFrame:CGRectMake(0.0, hiddenYOrigin, viewWidth, noticeViewHeight + 10.0)]; - } else { - self.noticeView = [[WBBlueGradientView alloc]initWithFrame:CGRectMake(0.0, hiddenYOrigin, viewWidth, noticeViewHeight + 10.0)]; - } - [view addSubview:self.noticeView]; - - // Make and add the icon view - UIImageView *iconView = [[UIImageView alloc]initWithFrame:CGRectMake(10.0, 10.0, 30.0, 30.0)]; - iconView.image = [UIImage imageWithContentsOfFile:noticeIconImageName]; - iconView.contentMode = UIViewContentModeScaleAspectFit; - iconView.alpha = 0.8; - [self.noticeView addSubview:iconView]; - - // Add the title label - [self.noticeView addSubview:self.titleLabel]; - - // Add the message label if it's an error notice - if (WBNoticeViewTypeError == noticeType) { - [self.noticeView addSubview:self.messageLabel]; - } - - // Add the drop shadow to the notice view - self.noticeView.layer.shadowColor = [[UIColor blackColor]CGColor]; - self.noticeView.layer.shadowOffset = CGSizeMake(0.0, 3); - self.noticeView.layer.shadowOpacity = 0.50; - self.noticeView.layer.masksToBounds = NO; - self.noticeView.layer.shouldRasterize = YES; - - // Go ahead, display it and then hide it automatically - [UIView animateWithDuration:duration animations:^ { - CGRect newFrame = self.noticeView.frame; - newFrame.origin.y = origin; - self.noticeView.frame = newFrame; - self.noticeView.alpha = alpha; - } completion:^ (BOOL finished) { - if (finished) { - // Display for a while, then hide it again - [UIView animateWithDuration:duration delay:delay options:UIViewAnimationOptionCurveEaseOut animations:^ { - CGRect newFrame = self.noticeView.frame; - newFrame.origin.y = hiddenYOrigin; - self.noticeView.frame = newFrame; - } completion:^ (BOOL finished) { - if (finished) { - // Cleanup - [self cleanup]; - } - }]; - } - }]; } } +#pragma mark - + +- (void)_showErrorNoticeInView:(UIView *)view + title:(NSString *)title + message:(NSString *)message + duration:(float)duration + delay:(float)delay + alpha:(float)alpha + yOrigin:(CGFloat)origin +{ + // Obtain the screen width + CGFloat viewWidth = view.frame.size.width; + + // Locate the images + NSString *path = [[[NSBundle mainBundle]resourcePath]stringByAppendingPathComponent:@"NoticeView.bundle"]; + NSString *noticeIconImageName = [path stringByAppendingPathComponent:@"notice_error_icon.png"]; + + NSInteger numberOfLines = 1; + CGFloat messageLineHeight = 30.0; + + // Make and add the title label + float titleYOrigin = 10.0; + + self.titleLabel = [[UILabel alloc]initWithFrame:CGRectMake(55.0, titleYOrigin, viewWidth - 70.0, 16.0)]; + self.titleLabel.textColor = [UIColor whiteColor]; + self.titleLabel.shadowOffset = CGSizeMake(0.0, -1.0); + self.titleLabel.shadowColor = [UIColor blackColor]; + self.titleLabel.font = [UIFont boldSystemFontOfSize:14.0]; + self.titleLabel.backgroundColor = [UIColor clearColor]; + self.titleLabel.text = title; + + // Make the message label + self.messageLabel = [[UILabel alloc]initWithFrame:CGRectMake(55.0, 10.0 + 10.0, viewWidth - 70.0, messageLineHeight)]; + self.messageLabel.font = [UIFont systemFontOfSize:13.0]; + self.messageLabel.textColor = [UIColor colorWithRed:239.0/255.0 green:167.0/255.0 blue:163.0/255.0 alpha:1.0]; + self.messageLabel.backgroundColor = [UIColor clearColor]; + self.messageLabel.text = message; + + // Calculate the number of lines it'll take to display the text + numberOfLines = [[self.messageLabel lines]count]; + self.messageLabel.numberOfLines = numberOfLines; + CGRect r = self.messageLabel.frame; + r.origin.y = self.titleLabel.frame.origin.y + self.titleLabel.frame.size.height;//(1 == numberOfLines) ? self.titleLabel.frame.origin.y : self.titleLabel.frame.origin.y - 11.0; + + // This step is needed to avoid having the UILabel center the text in the middle + [self.messageLabel sizeToFit]; + + // Now we can determine the height of one line of text + messageLineHeight = self.messageLabel.frame.size.height; + r.size.height = self.messageLabel.frame.size.height * numberOfLines; + r.size.width = viewWidth - 70.0; + self.messageLabel.frame = r; + + // Calculate the notice view height + float noticeViewHeight = 50.0; + float hiddenYOrigin = 0.0; + if (numberOfLines > 1) { + noticeViewHeight += (numberOfLines - 1) * messageLineHeight; + } + + // Make sure we hide completely the view, including its shadow + hiddenYOrigin = -noticeViewHeight - 20.0; + + // Make and add the notice view + self.noticeView = [[WBRedGradientView alloc]initWithFrame:CGRectMake(0.0, hiddenYOrigin, viewWidth, noticeViewHeight + 10.0)]; + [view addSubview:self.noticeView]; + + // Make and add the icon view + UIImageView *iconView = [[UIImageView alloc]initWithFrame:CGRectMake(10.0, 10.0, 20.0, 30.0)]; + iconView.image = [UIImage imageWithContentsOfFile:noticeIconImageName]; + iconView.contentMode = UIViewContentModeScaleAspectFit; + iconView.alpha = 0.8; + [self.noticeView addSubview:iconView]; + + // Add the title label + [self.noticeView addSubview:self.titleLabel]; + + // Add the message label + [self.noticeView addSubview:self.messageLabel]; + + // Add the drop shadow to the notice view + CALayer *noticeLayer = self.noticeView.layer; + noticeLayer.shadowColor = [[UIColor blackColor]CGColor]; + noticeLayer.shadowOffset = CGSizeMake(0.0, 3); + noticeLayer.shadowOpacity = 0.50; + noticeLayer.masksToBounds = NO; + noticeLayer.shouldRasterize = YES; + + self._duration = duration; + self._delay = delay; + self._alpha = alpha; + self._hiddenYOrigin = hiddenYOrigin; + + [self displayNoticeOfType:WBNoticeViewTypeError duration:duration delay:delay origin:origin hiddenYOrigin:hiddenYOrigin alpha:alpha]; +} + +- (void)_showSuccessNoticeInView:(UIView *)view + title:(NSString *)title + message:(NSString *)message + duration:(float)duration + delay:(float)delay + alpha:(float)alpha + yOrigin:(CGFloat)origin +{ + // Obtain the screen width + CGFloat viewWidth = view.frame.size.width; + + // Locate the images + NSString *path = [[[NSBundle mainBundle]resourcePath]stringByAppendingPathComponent:@"NoticeView.bundle"]; + NSString *noticeIconImageName = [path stringByAppendingPathComponent:@"notice_success_icon.png"]; + + NSInteger numberOfLines = 1; + CGFloat messageLineHeight = 30.0; + + // Make and add the title label + float titleYOrigin = 18.0; + self.titleLabel = [[UILabel alloc]initWithFrame:CGRectMake(55.0, titleYOrigin, viewWidth - 70.0, 16.0)]; + self.titleLabel.textColor = [UIColor whiteColor]; + self.titleLabel.shadowOffset = CGSizeMake(0.0, -1.0); + self.titleLabel.shadowColor = [UIColor blackColor]; + self.titleLabel.font = [UIFont boldSystemFontOfSize:14.0]; + self.titleLabel.backgroundColor = [UIColor clearColor]; + self.titleLabel.text = title; + + // Calculate the notice view height + float noticeViewHeight = 40.0; + float hiddenYOrigin = 0.0; + if (numberOfLines > 1) { + noticeViewHeight += (numberOfLines - 1) * messageLineHeight; + } + + // Make sure we hide completely the view, including its shadow + hiddenYOrigin = -noticeViewHeight - 20.0; + + // Make and add the notice view + self.noticeView = [[WBBlueGradientView alloc]initWithFrame:CGRectMake(0.0, hiddenYOrigin, viewWidth, noticeViewHeight + 10.0)]; + [view addSubview:self.noticeView]; + + // Make and add the icon view + UIImageView *iconView = [[UIImageView alloc]initWithFrame:CGRectMake(10.0, 10.0, 20.0, 30.0)]; + iconView.image = [UIImage imageWithContentsOfFile:noticeIconImageName]; + iconView.contentMode = UIViewContentModeScaleAspectFit; + iconView.alpha = 0.8; + [self.noticeView addSubview:iconView]; + + // Add the title label + [self.noticeView addSubview:self.titleLabel]; + + // Add the drop shadow to the notice view + CALayer *noticeLayer = self.noticeView.layer; + noticeLayer.shadowColor = [[UIColor blackColor]CGColor]; + noticeLayer.shadowOffset = CGSizeMake(0.0, 3); + noticeLayer.shadowOpacity = 0.50; + noticeLayer.masksToBounds = NO; + noticeLayer.shouldRasterize = YES; + + self._duration = duration; + self._delay = delay; + self._alpha = alpha; + self._hiddenYOrigin = hiddenYOrigin; + + [self displayNoticeOfType:WBNoticeViewTypeSuccess duration:duration delay:delay origin:origin hiddenYOrigin:hiddenYOrigin alpha:alpha]; +} + +- (void)_showStickyNoticeInView:(UIView *)view + title:(NSString *)title + message:(NSString *)message + duration:(float)duration + delay:(float)delay + alpha:(float)alpha + yOrigin:(CGFloat)origin +{ + // Obtain the screen width + CGFloat viewWidth = view.frame.size.width; + + // Locate the images + NSString *path = [[[NSBundle mainBundle]resourcePath]stringByAppendingPathComponent:@"NoticeView.bundle"]; + NSString *noticeIconImageName = [path stringByAppendingPathComponent:@"up.png"]; + + NSInteger numberOfLines = 1; + CGFloat messageLineHeight = 30.0; + + // Make and add the title label + self.titleLabel = [[UILabel alloc]initWithFrame:CGRectMake(55.0, 8.0, viewWidth - 70.0, 16.0)]; + self.titleLabel.textColor = [UIColor blackColor]; + self.titleLabel.shadowOffset = CGSizeMake(0.0, 1.0); + self.titleLabel.shadowColor = [UIColor whiteColor]; + self.titleLabel.font = [UIFont boldSystemFontOfSize:12.0]; + self.titleLabel.backgroundColor = [UIColor clearColor]; + self.titleLabel.text = title; + [self.titleLabel sizeToFit]; + CGRect frame = self.titleLabel.frame; + if (frame.size.width > 260) { + frame.size.width = 260; + self.titleLabel.frame = frame; + } + + // Calculate the notice view height + float noticeViewHeight = 40.0; + float hiddenYOrigin = 0.0; + if (numberOfLines > 1) { + noticeViewHeight += (numberOfLines - 1) * messageLineHeight; + } + + // Make sure we hide completely the view, including its shadow + hiddenYOrigin = -noticeViewHeight - 20.0; + + // Make and add the notice view + self.noticeView = [[WBGrayGradientView alloc]initWithFrame:CGRectMake(0.0, hiddenYOrigin, viewWidth, 32)]; + [view addSubview:self.noticeView]; + + // Center the message in the middle of the notice + frame = self.titleLabel.frame; + frame.origin.x = (self.noticeView.frame.size.width - frame.size.width) / 2; + self.titleLabel.frame = frame; + + // Make and add the icon view + UIImageView *iconView = nil; + CGFloat labelLeftPos = self.titleLabel.frame.origin.x; + iconView = [[UIImageView alloc]initWithFrame:CGRectMake(labelLeftPos - 25, 9.0, 18, 13.0)]; + iconView.image = [UIImage imageWithContentsOfFile:noticeIconImageName]; + iconView.contentMode = UIViewContentModeScaleAspectFit; + iconView.alpha = 0.8; + [self.noticeView addSubview:iconView]; + + // Add the title label + [self.noticeView addSubview:self.titleLabel]; + + // Add the drop shadow to the notice view + CALayer *noticeLayer = self.noticeView.layer; + noticeLayer.shadowColor = [[UIColor blackColor]CGColor]; + noticeLayer.shadowOffset = CGSizeMake(0.0, 3); + noticeLayer.shadowOpacity = 0.50; + noticeLayer.masksToBounds = NO; + noticeLayer.shouldRasterize = YES; + + // Add an invisible button that responds to a manual dismiss + self._currentNotice = self; + frame = self.noticeView.frame; + UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; + frame.origin.x = frame.origin.y = 0.0; + button.frame = frame; + [button addTarget:self._currentNotice action:@selector(dismissStickyNotice:) forControlEvents:UIControlEventTouchUpInside]; + [self.noticeView addSubview:button]; + + self._duration = duration; + self._delay = delay; + self._alpha = alpha; + self._hiddenYOrigin = hiddenYOrigin; + + NSLog(@"%@", self.noticeView.subviews); + + [self displayNoticeOfType:WBNoticeViewTypeSticky duration:duration delay:delay origin:origin hiddenYOrigin:hiddenYOrigin alpha:alpha]; +} + +#pragma mark - + +- (void)displayNoticeOfType:(WBNoticeViewType)noticeType duration:(CGFloat)duration delay:(CGFloat)delay origin:(CGFloat)origin hiddenYOrigin:(CGFloat)hiddenYOrigin alpha:(CGFloat)alpha +{ + // Go ahead, display it + [UIView animateWithDuration:duration animations:^ { + CGRect newFrame = self.noticeView.frame; + newFrame.origin.y = origin; + self.noticeView.frame = newFrame; + self.noticeView.alpha = alpha; + } completion:^ (BOOL finished) { + if (finished) { + // if it's not sticky, hide it automatically + if (WBNoticeViewTypeSticky != noticeType) { + // Display for a while, then hide it again + [self dismissNoticeOfType:noticeType duration:duration delay:delay hiddenYOrigin:hiddenYOrigin]; + } + } + }]; +} + +- (void)dismissNoticeOfType:(WBNoticeViewType)noticeType duration:(CGFloat)duration delay:(CGFloat)delay hiddenYOrigin:(CGFloat)hiddenYOrigin +{ + [UIView animateWithDuration:duration delay:delay options:UIViewAnimationOptionCurveEaseOut animations:^ { + CGRect newFrame = self.noticeView.frame; + newFrame.origin.y = hiddenYOrigin; + self.noticeView.frame = newFrame; + } completion:^ (BOOL finished) { + if (finished) { + // Cleanup + [self cleanup]; + } + }]; +} + +- (IBAction)dismissStickyNotice:(id)sender +{ + // Triggered manually by the sticky notice + [self dismissNoticeOfType:WBNoticeViewTypeSticky duration:self._duration delay:self._delay hiddenYOrigin:self._hiddenYOrigin]; +} + +#pragma mark - + - (void)cleanup { [self.noticeView removeFromSuperview]; self.noticeView = nil; self.titleLabel = nil; self.messageLabel = nil; + self._currentNotice = nil; } - (void)dealloc @@ -276,6 +553,4 @@ [self cleanup]; } - - @end diff --git a/NoticeView/WBNoticeView/WBNoticeView_Private.h b/NoticeView/WBNoticeView/WBNoticeView_Private.h index d839b30..887a56d 100644 --- a/NoticeView/WBNoticeView/WBNoticeView_Private.h +++ b/NoticeView/WBNoticeView/WBNoticeView_Private.h @@ -22,6 +22,14 @@ alpha:(float)alpha yOrigin:(CGFloat)origin; +- (void)_showErrorNoticeInView:(UIView *)view + title:(NSString *)title + message:(NSString *)message + duration:(float)duration + delay:(float)delay + alpha:(float)alpha + yOrigin:(CGFloat)origin; + @end #endif diff --git a/NoticeView/WBNoticeView/WBStickyNoticeView.h b/NoticeView/WBNoticeView/WBStickyNoticeView.h new file mode 100644 index 0000000..07c040f --- /dev/null +++ b/NoticeView/WBNoticeView/WBStickyNoticeView.h @@ -0,0 +1,15 @@ +// +// WBStickyNoticeView.h +// NoticeView +// +// Created by Tito Ciuro on 6/4/12. +// Copyright (c) 2012 Tito Ciuro. All rights reserved. +// + +#import "WBBaseNoticeView.h" + +@interface WBStickyNoticeView : WBBaseNoticeView + ++ (WBStickyNoticeView *)stickyNoticeInView:(UIView *)view title:(NSString *)title; + +@end diff --git a/NoticeView/WBNoticeView/WBStickyNoticeView.m b/NoticeView/WBNoticeView/WBStickyNoticeView.m new file mode 100644 index 0000000..a6bc825 --- /dev/null +++ b/NoticeView/WBNoticeView/WBStickyNoticeView.m @@ -0,0 +1,35 @@ +// +// WBStickyNoticeView.m +// NoticeView +// +// Created by Tito Ciuro on 6/4/12. +// Copyright (c) 2012 Tito Ciuro. All rights reserved. +// + +#import "WBStickyNoticeView.h" +#import "WBNoticeView_Private.h" + +@implementation WBStickyNoticeView + +@synthesize title; + ++ (WBStickyNoticeView *)stickyNoticeInView:(UIView *)view title:(NSString *)title +{ + WBStickyNoticeView *notice = [[WBStickyNoticeView alloc]initWithView:view title:title]; + + return notice; +} + +- (void)show +{ + [self _showNoticeOfType:WBNoticeViewTypeSticky + view:self.view + title:self.title + message:nil + duration:self.duration + delay:0.0 + alpha:self.alpha + yOrigin:self.originY]; +} + +@end diff --git a/NoticeView/WBViewController.h b/NoticeView/WBViewController.h index 1ad4fdf..d02dc45 100644 --- a/NoticeView/WBViewController.h +++ b/NoticeView/WBViewController.h @@ -34,11 +34,11 @@ - (IBAction)showSmallErrorNotice:(id)sender; - (IBAction)showLargeErrorNotice:(id)sender; - (IBAction)showSmallSuccessNotice:(id)sender; - - (IBAction)showSmallErrorNoticeBelow:(id)sender; - (IBAction)showLargeErrorNoticeBelow:(id)sender; - (IBAction)showSmallSuccessNoticeBelow:(id)sender; - +- (IBAction)showSmallStickyNoticeBelow:(id)sender; - (IBAction)showSmallErrorNoticeAndPush:(id)sender; +- (IBAction)showStickyNoticeAndPush:(id)sender; @end diff --git a/NoticeView/WBViewController.m b/NoticeView/WBViewController.m index ecca9b5..170ac48 100644 --- a/NoticeView/WBViewController.m +++ b/NoticeView/WBViewController.m @@ -29,6 +29,7 @@ #import "WBNoticeView.h" #import "WBErrorNoticeView.h" #import "WBSuccessNoticeView.h" +#import "WBStickyNoticeView.h" @interface WBViewController () @@ -81,6 +82,12 @@ [notice show]; } +- (IBAction)showSmallStickyNotice:(id)sender +{ + WBStickyNoticeView *notice = [WBStickyNoticeView stickyNoticeInView:self.view title:@"7 New Tweets."]; + [notice show]; +} + - (IBAction)showSmallErrorNoticeBelow:(id)sender { WBErrorNoticeView *notice = [WBErrorNoticeView errorNoticeInView:self.view title:@"Network Error" message:@"Check your network connection."]; @@ -111,6 +118,15 @@ [notice show]; } +- (IBAction)showSmallStickyNoticeBelow:(id)sender +{ + WBStickyNoticeView *notice = [WBStickyNoticeView stickyNoticeInView:self.view title:@"7 New Tweets arrived somewhere from the intertubes."]; + + notice.originY = self.headerView.frame.size.height; + + [notice show]; +} + - (IBAction)showSmallErrorNoticeAndPush:(id)sender { WBErrorNoticeView *notice = [WBErrorNoticeView errorNoticeInView:self.view title:@"Network Error" message:@"Check your network connection."]; @@ -119,4 +135,12 @@ [self.navigationController pushViewController: [[WBViewController alloc] init] animated:YES]; } +- (IBAction)showStickyNoticeAndPush:(id)sender +{ + WBStickyNoticeView *notice = [WBStickyNoticeView stickyNoticeInView:self.view title:@"7 New Tweets arrived somewhere from the intertubes."]; + [notice show]; + + [self.navigationController pushViewController: [[WBViewController alloc] init] animated:YES]; +} + @end diff --git a/NoticeView/en.lproj/MainStoryboard.storyboard b/NoticeView/en.lproj/MainStoryboard.storyboard index 2bf09f0..201eb8d 100644 --- a/NoticeView/en.lproj/MainStoryboard.storyboard +++ b/NoticeView/en.lproj/MainStoryboard.storyboard @@ -16,7 +16,7 @@ - + + + @@ -163,8 +208,10 @@ + +