Fixed #8: Add a sticky notice view and refactor the code a bit

This commit is contained in:
Tito Ciuro
2012-06-06 21:56:54 -07:00
parent 885038e61d
commit 53d02f22d7
12 changed files with 597 additions and 117 deletions

View File

@@ -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 = "<group>"; };
746CBD061570A8FA00B844B1 /* WBSuccessNoticeView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WBSuccessNoticeView.h; sourceTree = "<group>"; };
746CBD071570A8FA00B844B1 /* WBSuccessNoticeView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WBSuccessNoticeView.m; sourceTree = "<group>"; };
748A6A57157D0B74003C7655 /* WBGrayGradientView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WBGrayGradientView.h; sourceTree = "<group>"; };
748A6A58157D0B74003C7655 /* WBGrayGradientView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WBGrayGradientView.m; sourceTree = "<group>"; };
748A6A5B157D0D06003C7655 /* WBStickyNoticeView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WBStickyNoticeView.h; sourceTree = "<group>"; };
748A6A5C157D0D06003C7655 /* WBStickyNoticeView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WBStickyNoticeView.m; sourceTree = "<group>"; };
7492FA41157C8CD700FB834C /* WBBlueGradientView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WBBlueGradientView.h; sourceTree = "<group>"; };
7492FA42157C8CD700FB834C /* WBBlueGradientView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WBBlueGradientView.m; sourceTree = "<group>"; };
7492FA43157C8CD700FB834C /* WBRedGradientView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WBRedGradientView.h; sourceTree = "<group>"; };
@@ -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;
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -0,0 +1,13 @@
//
// WBGrayGradientView.h
// GradientView
//
// Created by Tito Ciuro on 6/3/12.
// Copyright (c) 2012 Webbo, LLC. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface WBGrayGradientView : UIView
@end

View File

@@ -0,0 +1,42 @@
//
// WBGrayGradientView.m
// GradientView
//
// Created by Tito Ciuro on 6/3/12.
// Copyright (c) 2012 Webbo, LLC. All rights reserved.
//
#import <QuartzCore/QuartzCore.h>
#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

View File

@@ -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

View File

@@ -10,6 +10,7 @@
#import "WBNoticeView_Private.h"
#import "WBRedGradientView.h"
#import "WBBlueGradientView.h"
#import "WBGrayGradientView.h"
#import "UILabel+WBExtensions.h"
#import <QuartzCore/QuartzCore.h>
@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -16,7 +16,7 @@
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="Vg3-qF-Q8T">
<rect key="frame" x="170" y="80" width="130" height="37"/>
<rect key="frame" x="170" y="64" width="130" height="37"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="11"/>
<state key="normal" title="Small Error Below">
@@ -31,7 +31,7 @@
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="XR3-Kf-0Pf">
<rect key="frame" x="170" y="125" width="130" height="37"/>
<rect key="frame" x="170" y="109" width="130" height="37"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="11"/>
<state key="normal" title="Large Error Below">
@@ -46,7 +46,7 @@
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="gi6-oq-xIu">
<rect key="frame" x="170" y="170" width="130" height="37"/>
<rect key="frame" x="170" y="154" width="130" height="37"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="11"/>
<state key="normal" title="Small Success Below">
@@ -65,7 +65,7 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
</imageView>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="Xwf-eU-mzM">
<rect key="frame" x="22" y="80" width="130" height="37"/>
<rect key="frame" x="22" y="64" width="130" height="37"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="11"/>
<state key="normal" title="Small Error">
@@ -80,7 +80,7 @@
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="oNn-y7-T1N">
<rect key="frame" x="22" y="125" width="130" height="37"/>
<rect key="frame" x="22" y="109" width="130" height="37"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="11"/>
<state key="normal" title="Large Error">
@@ -95,7 +95,7 @@
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="WpV-6q-VuB">
<rect key="frame" x="22" y="170" width="130" height="37"/>
<rect key="frame" x="22" y="154" width="130" height="37"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="11"/>
<state key="normal" title="Small Success">
@@ -109,10 +109,40 @@
<action selector="showSmallSuccessNotice:" destination="2" eventType="touchUpInside" id="IZc-Hp-Izk"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="cee-Xq-cSc">
<rect key="frame" x="95" y="256" width="130" height="37"/>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="ohN-nb-77O">
<rect key="frame" x="170" y="199" width="130" height="37"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="11"/>
<state key="normal" title="Sticky Below">
<color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<state key="highlighted">
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<action selector="showSmallStickyNoticeBelow:" destination="2" eventType="touchUpInside" id="em9-L4-KoA"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="Uso-1A-Af2">
<rect key="frame" x="22" y="199" width="130" height="37"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="11"/>
<state key="normal" title="Sticky">
<color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<state key="highlighted">
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<action selector="showSmallStickyNotice:" destination="2" eventType="touchUpInside" id="F96-6G-a61"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="cee-Xq-cSc">
<rect key="frame" x="22" y="244" width="130" height="37"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="11"/>
<state key="normal" title="Show And Push">
<color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
@@ -124,6 +154,21 @@
<action selector="showSmallErrorNoticeAndPush:" destination="2" eventType="touchUpInside" id="O2w-xz-8eD"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="FBJ-Ol-wtM">
<rect key="frame" x="170" y="244" width="130" height="37"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="11"/>
<state key="normal" title="Sticky Push">
<color key="titleColor" red="0.19607843459999999" green="0.30980393290000002" blue="0.52156865600000002" alpha="1" colorSpace="calibratedRGB"/>
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<state key="highlighted">
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<action selector="showStickyNoticeAndPush:" destination="2" eventType="touchUpInside" id="5zd-aY-Mhi"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
@@ -163,8 +208,10 @@
<relationship kind="action" name="showSmallErrorNotice:"/>
<relationship kind="action" name="showSmallErrorNoticeAndPush:"/>
<relationship kind="action" name="showSmallErrorNoticeBelow:"/>
<relationship kind="action" name="showSmallStickyNoticeBelow:"/>
<relationship kind="action" name="showSmallSuccessNotice:"/>
<relationship kind="action" name="showSmallSuccessNoticeBelow:"/>
<relationship kind="action" name="showStickyNoticeAndPush:"/>
<relationship kind="outlet" name="headerView" candidateClass="UIImageView"/>
</relationships>
</class>