This commit is contained in:
Terry Worona
2013-05-20 17:42:41 -07:00
parent 825895efc5
commit 4d00ad9374
16 changed files with 1209 additions and 6 deletions

View File

@@ -0,0 +1,35 @@
//
// MessageBarManager.h
//
// Created by Terry Worona on 5/13/13.
// Copyright (c) 2013 Terry Worona. All rights reserved.
//
#import <Foundation/Foundation.h>
typedef enum {
MessageBarMessageTypeError,
MessageBarMessageTypeSuccess,
MessageBarMessageTypeInfo,
MessageBarMessageTypeLogo
} MessageBarMessageType;
@interface MessageBarManager : NSObject
+ (MessageBarManager *)sharedInstance;
+ (CGFloat)durationForMessageType:(MessageBarMessageType)messageType;
- (void)showGenericServerError;
- (void)showSaveErrorWithResourceName:(NSString*)resource;
- (void)showMessageWithTitle:(NSString*)title description:(NSString*)description type:(MessageBarMessageType)type;
- (void)showMessageWithTitle:(NSString*)title description:(NSString*)description type:(MessageBarMessageType)type callback:(void (^)())callback;
- (void)showMessageWithTitle:(NSString*)title description:(NSString*)description type:(MessageBarMessageType)type forDuration:(CGFloat)duration;
- (void)showMessageWithTitle:(NSString*)title description:(NSString*)description type:(MessageBarMessageType)type forDuration:(CGFloat)duration callback:(void (^)())callback;
- (void)showAppUpgradeAvailableWithCallback:(void (^)())buttonCallback;
- (void)showMessageWithTitle:(NSString*)title description:(NSString*)description type:(MessageBarMessageType)type withButtonCallback:(void (^)())buttonCallback;
- (void)showMessageWithTitle:(NSString*)title description:(NSString*)description type:(MessageBarMessageType)type withButtonCallback:(void (^)())buttonCallback callback:(void (^)())callback;
@end

553
Classes/MessageBarManager.m Normal file
View File

@@ -0,0 +1,553 @@
//
// MessageBarManager.m
//
// Created by Terry Worona on 5/13/13.
// Copyright (c) 2013 Terry Worona. All rights reserved.
//
#import "GAMessageBarManager.h"
// Constants
#import "GAConstants.h"
// quartz
#import <QuartzCore/QuartzCore.h>
// Delegate
#import "AppDelegate.h"
// Drawing
#import "GADrawUtils.h"
#define kGAMessageBarAlpha 0.96
#define kGAMessageBarPadding 10
#define kGAMessageBarButtonWidth 60
#define kGAMessageBarButtonHeight 30
#define kGAMessageBarMaxDescriptionHeight 250
#define kGAMessageBarIconSize 36
#define kGAMessageBarRegularDisplayDelay 3.0
#define kGAMessageBarErrorDisplayDelay 5.0
#define kGAMessageBarTextOffset 2.0
typedef enum {
GAMessageViewTypeVirgin = 1,
GAMessageViewTypeHit
} GAMessageViewType;
@class GAMessageView;
@interface GAMessageView : UIView
@property (nonatomic, strong) NSString *titleString;
@property (nonatomic, strong) NSString *descriptionString;
@property (nonatomic, assign) GAMessageBarMessageType messageType;
@property (nonatomic, strong) UIImageView *shadowView;
@property (nonatomic, assign) BOOL hasCallback;
@property (nonatomic, strong) NSArray *callbacks;
@property (nonatomic, assign) BOOL hasButtonCallback;
@property (nonatomic, strong) NSArray *buttonCallbacks;
@property (nonatomic, assign, getter = isHit) BOOL hit;
@property (nonatomic, assign, readonly) CGFloat height;
@property (nonatomic, assign, readonly) CGFloat width;
@property (nonatomic, assign) CGFloat duration;
@property (nonatomic, strong) UIButton *button;
- (id)initWithTitle:(NSString*)title description:(NSString*)description type:(GAMessageBarMessageType)type;
- (id)initWithTitle:(NSString*)title description:(NSString*)description type:(GAMessageBarMessageType)type buttonText:(NSString*)buttonText;
- (void)buttonPressed:(id)sender;
@end
@interface GAMessageBarManager ()
@property (nonatomic, strong) NSMutableArray *messageBarQueue;
@property (nonatomic, assign, getter = isMessageVisible) BOOL messageVisible;
@property (nonatomic, assign) CGFloat messageBarOffset;
- (void)showNextMessage;
- (void)itemSelected:(UITapGestureRecognizer*)recognizer;
@end
@implementation GAMessageBarManager
@synthesize messageBarQueue = _messageBarQueue;
@synthesize messageVisible = _messageVisible;
@synthesize messageBarOffset = _messageBarOffset;
#pragma mark - Singleton
+ (GAMessageBarManager *)sharedInstance
{
static dispatch_once_t pred;
static GAMessageBarManager *instance = nil;
dispatch_once(&pred, ^{ instance = [[self alloc] init]; });
return instance;
}
#pragma mark - Static
+ (CGFloat)durationForMessageType:(GAMessageBarMessageType)messageType
{
switch (messageType) {
case GAMessageBarMessageTypeError:
return kGAMessageBarErrorDisplayDelay;
break;
case GAMessageBarMessageTypeSuccess:
return kGAMessageBarRegularDisplayDelay;
break;
case GAMessageBarMessageTypeInfo:
return kGAMessageBarRegularDisplayDelay;
break;
case GAMessageBarMessageTypeLogo:
return kGAMessageBarRegularDisplayDelay;
break;
default:
break;
}
return kGAMessageBarRegularDisplayDelay;
}
#pragma mark - Alloc/Init
-(id)init
{
if(self = [super init]) {
_messageBarQueue = [[NSMutableArray alloc] init];
_messageVisible = NO;
_messageBarOffset = [[UIApplication sharedApplication] statusBarFrame].size.height;
}
return self;
}
#pragma mark - Public
- (void)showGenericServerError
{
[self showMessageWithTitle:kGAStringMessageUnexpectedErrorTitle description:kGAStringMessageUnexpectedErrorMessage type:GAMessageBarMessageTypeError];
}
- (void)showSaveErrorWithResourceName:(NSString*)resource
{
[self showMessageWithTitle:kGAStringMessageResourceSaveErrorTitle description:[NSString stringWithFormat:kGAStringMessageResourceSaveErrorMessage, [resource lowercaseString]] type:GAMessageBarMessageTypeError];
}
- (void)showMessageWithTitle:(NSString*)title description:(NSString*)description type:(GAMessageBarMessageType)type
{
[self showMessageWithTitle:title description:description type:type forDuration:[GAMessageBarManager durationForMessageType:type] callback:nil];
}
- (void)showMessageWithTitle:(NSString*)title description:(NSString*)description type:(GAMessageBarMessageType)type callback:(void (^)())callback
{
[self showMessageWithTitle:title description:description type:type forDuration:[GAMessageBarManager durationForMessageType:type] callback:callback];
}
- (void)showMessageWithTitle:(NSString*)title description:(NSString*)description type:(GAMessageBarMessageType)type forDuration:(CGFloat)duration
{
[self showMessageWithTitle:title description:description type:type forDuration:duration callback:nil];
}
- (void)showMessageWithTitle:(NSString*)title description:(NSString*)description type:(GAMessageBarMessageType)type forDuration:(CGFloat)duration callback:(void (^)())callback
{
GAMessageView *messageView = [[GAMessageView alloc] initWithTitle:title description:description type:type];
messageView.callbacks = callback ? [NSArray arrayWithObject:callback] : [NSArray array];
messageView.hasCallback = callback ? YES : NO;
messageView.duration = duration;
messageView.hidden = YES;
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[delegate.window insertSubview:messageView atIndex:1];
[_messageBarQueue addObject:messageView];
if (!_messageVisible){
[self showNextMessage];
}
}
- (void)showAppUpgradeAvailableWithCallback:(void (^)())buttonCallback
{
GAMessageView *messageView = [[GAMessageView alloc] initWithTitle:kGAStringMessageUpdateMessageTitle description:kGAStringMessageUpdateMessage type:GAMessageBarMessageTypeLogo buttonText:kGAStringLabelView];
messageView.hasButtonCallback = buttonCallback ? YES : NO;
messageView.buttonCallbacks = buttonCallback ? [NSArray arrayWithObject:buttonCallback] : [NSArray array];
messageView.duration = [GAMessageBarManager durationForMessageType:GAMessageBarMessageTypeLogo];
messageView.hidden = YES;
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[delegate.window insertSubview:messageView atIndex:1];
[_messageBarQueue addObject:messageView];
if (!_messageVisible){
[self showNextMessage];
}
}
- (void)showMessageWithTitle:(NSString*)title description:(NSString*)description type:(GAMessageBarMessageType)type withButtonCallback:(void (^)())buttonCallback
{
[self showMessageWithTitle:title description:description type:type withButtonCallback:buttonCallback callback:nil];
}
- (void)showMessageWithTitle:(NSString*)title description:(NSString*)description type:(GAMessageBarMessageType)type withButtonCallback:(void (^)())buttonCallback callback:(void (^)())callback
{
GAMessageView *messageView = [[GAMessageView alloc] initWithTitle:title description:description type:type buttonText:kGAStringLabelView];
messageView.hasButtonCallback = buttonCallback ? YES : NO;
messageView.buttonCallbacks = buttonCallback ? [NSArray arrayWithObject:buttonCallback] : [NSArray array];
messageView.callbacks = callback ? [NSArray arrayWithObject:callback] : [NSArray array];
messageView.hasCallback = callback ? YES : NO;
messageView.duration = [GAMessageBarManager durationForMessageType:type];
messageView.hidden = YES;
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[delegate.window insertSubview:messageView atIndex:1];
[_messageBarQueue addObject:messageView];
if (!_messageVisible){
[self showNextMessage];
}
}
#pragma mark - Private
- (void)showNextMessage
{
if ([_messageBarQueue count] > 0){
_messageVisible = YES;
GAMessageView *messageView = [_messageBarQueue objectAtIndex:0];
messageView.frame = CGRectMake(0, -[messageView height], [messageView width], [messageView height]);
messageView.hidden = NO;
[messageView setNeedsDisplay];
UITapGestureRecognizer *gest = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(itemSelected:)];
[messageView addGestureRecognizer:gest];
if (messageView){
[_messageBarQueue removeObject:messageView];
[UIView animateWithDuration:kGANumericDefaultAnimationDuration animations:^{
[messageView setFrame:CGRectMake(messageView.frame.origin.x, _messageBarOffset + messageView.frame.origin.y + [messageView height], [messageView width], [messageView height])]; // slide down
}];
[self performSelector:@selector(itemSelected:) withObject:messageView afterDelay:messageView.duration];
}
}
}
#pragma mark - Gestures
- (void)itemSelected:(id)sender
{
GAMessageView *messageView = nil;
BOOL itemHit = NO;
if ([sender isKindOfClass:[UIGestureRecognizer class]]){
messageView = (GAMessageView*)((UIGestureRecognizer*)sender).view;
itemHit = YES;
}
else if ([sender isKindOfClass:[GAMessageView class]]){
messageView = (GAMessageView*)sender;
}
if (messageView && ![messageView isHit]){
messageView.hit = YES;
[UIView animateWithDuration:kGANumericDefaultAnimationDuration animations:^{
[messageView setFrame:CGRectMake(messageView.frame.origin.x, messageView.frame.origin.y - [messageView height] - _messageBarOffset, [messageView width], [messageView height])]; // slide back up
} completion:^(BOOL finished) {
_messageVisible = NO;
[messageView removeFromSuperview];
if (itemHit){
if ([messageView.callbacks count] > 0){
id obj = [messageView.callbacks objectAtIndex:0];
if (![obj isEqual:[NSNull null]]) {
((void (^)())obj)();
}
}
}
if([_messageBarQueue count] > 0) {
[self showNextMessage];
}
}];
}
}
@end
static UIFont *titleFont = nil;
static UIColor *titleColor = nil;
static UIFont *descriptionFont = nil;
static UIColor *descriptionColor = nil;
static UIColor *shadowColor = nil;
@implementation GAMessageView
@synthesize titleString = _titleString;
@synthesize descriptionString = _descriptionString;
@synthesize messageType = _messageType;
@synthesize shadowView = _shadowView;
@synthesize hasCallback = _hasCallback;
@synthesize callbacks = _callbacks;
@synthesize hasButtonCallback = _hasButtonCallback;
@synthesize buttonCallbacks = _buttonCallbacks;
@synthesize hit = _hit;
@synthesize width = _width;
@synthesize height = _height;
@synthesize duration = _duration;
@synthesize button = _button;
#pragma mark - Alloc/Init
- (id)initWithTitle:(NSString*)title description:(NSString*)description type:(GAMessageBarMessageType)type
{
return [self initWithTitle:title description:description type:type buttonText:nil];
}
- (id)initWithTitle:(NSString*)title description:(NSString*)description type:(GAMessageBarMessageType)type buttonText:(NSString*)buttonText
{
self = [super initWithFrame:CGRectZero];
if (self){
self.backgroundColor = [UIColor clearColor];
self.clipsToBounds = NO;
self.userInteractionEnabled = YES;
_shadowView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:kGAImageBarShadowTop]];
[self addSubview:_shadowView];
_titleString = title;
_descriptionString = description;
_messageType = type;
titleFont = kGAFontMessageBarTitle;
titleColor = [UIColor colorWithWhite:0.95 alpha:1.0];
descriptionFont = kGAFontMessageBarMessage;
descriptionColor = [UIColor colorWithWhite:0.9 alpha:1.0];
shadowColor = [UIColor colorWithWhite:0.2 alpha:0.25];
_height = 0.0;
_width = 0.0;
_hasCallback = NO;
_hit = NO;
if (buttonText){
_button = [UIButton buttonWithType:UIButtonTypeCustom];
[_button addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
_button.titleLabel.font = [UIFont fontWithName:kGAFontSommetRoundedBlack size:14.0];
_button.titleLabel.adjustsFontSizeToFitWidth = YES;
_button.titleLabel.shadowOffset = CGSizeMake(0, -1);
_button.titleLabel.textAlignment = UITextAlignmentCenter;
[_button setTitleShadowColor:kGAColorDarkGray forState:UIControlStateNormal];
[_button setTitleShadowColor:kGAColorDarkGray forState:UIControlStateDisabled];
[_button setTitleShadowColor:kGAColorDarkGray forState:UIControlStateSelected];
[_button setTitleShadowColor:[UIColor blackColor] forState:UIControlStateHighlighted];
[_button setTitleShadowColor:[UIColor blackColor] forState:UIControlStateHighlighted | UIControlStateSelected];
[_button setTitle:buttonText forState:UIControlStateNormal];
[_button setTitle:buttonText forState:UIControlStateDisabled];
[_button setTitle:buttonText forState:UIControlStateSelected];
[_button setTitle:buttonText forState:UIControlStateHighlighted];
[_button setTitle:buttonText forState:UIControlStateHighlighted | UIControlStateSelected];
UIImage *buttonBackgroundImage = [UIImage imageNamed:kGAImageButtonNotification];
buttonBackgroundImage = [buttonBackgroundImage stretchableImageWithLeftCapWidth:ceil(buttonBackgroundImage.size.width/2) topCapHeight:ceil(buttonBackgroundImage.size.height/2)];
UIImage *buttonBackgroundDepressedImage = [UIImage imageNamed:kGAImageButtonNotificationDepressed];
buttonBackgroundDepressedImage = [buttonBackgroundDepressedImage stretchableImageWithLeftCapWidth:ceil(buttonBackgroundDepressedImage.size.width/2) topCapHeight:ceil(buttonBackgroundDepressedImage.size.height/2)];
[_button setBackgroundImage:buttonBackgroundImage forState:UIControlStateNormal];
[_button setBackgroundImage:buttonBackgroundImage forState:UIControlStateDisabled];
[_button setBackgroundImage:buttonBackgroundDepressedImage forState:UIControlStateSelected];
[_button setBackgroundImage:buttonBackgroundDepressedImage forState:UIControlStateHighlighted];
[_button setBackgroundImage:buttonBackgroundDepressedImage forState:UIControlStateHighlighted | UIControlStateSelected];
[_button setNeedsDisplay];
[self addSubview:_button];
}
}
return self;
}
#pragma mark - Button Presses
- (void)buttonPressed:(id)sender
{
if ([_buttonCallbacks count] > 0){
id obj = [_buttonCallbacks objectAtIndex:0];
if (![obj isEqual:[NSNull null]]) {
((void (^)())obj)();
[[GAMessageBarManager sharedInstance] performSelector:@selector(itemSelected:) withObject:self afterDelay:0];
}
}
}
#pragma mark - Drawing
- (void)drawRect:(CGRect)rect
{
[super drawRect:rect];
CGContextRef context = UIGraphicsGetCurrentContext();
// bg gradient
CGRect gradientRect = CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
CGContextSaveGState(context);
{
switch (_messageType) {
case GAMessageBarMessageTypeError:
drawVerticalLinearGradient(context, gradientRect,
[UIColor colorWithRed:0.858 green:0.329 blue:0.309 alpha:kGAMessageBarAlpha].CGColor, // light red
[UIColor colorWithRed:0.756 green:0.019 blue:0.0 alpha:kGAMessageBarAlpha].CGColor); // dark red
break;
case GAMessageBarMessageTypeSuccess:
drawVerticalLinearGradient(context, gradientRect,
[UIColor colorWithRed:0.149 green:0.749 blue:0.149 alpha:kGAMessageBarAlpha].CGColor, // light green
[UIColor colorWithRed:0.0 green:0.549 blue:0.0 alpha:kGAMessageBarAlpha].CGColor); // dark green
break;
case GAMessageBarMessageTypeInfo:
drawVerticalLinearGradient(context, gradientRect,
[UIColor colorWithRed:0.0 green:0.776 blue:0.831 alpha:kGAMessageBarAlpha].CGColor, // light teal
[UIColor colorWithRed:0.0 green:0.560 blue:0.6 alpha:kGAMessageBarAlpha].CGColor); // dark teal
break;
case GAMessageBarMessageTypeLogo:
drawVerticalLinearGradient(context, gradientRect,
[UIColor colorWithRed:0.0 green:0.776 blue:0.831 alpha:kGAMessageBarAlpha].CGColor, // light teal
[UIColor colorWithRed:0.0 green:0.560 blue:0.6 alpha:kGAMessageBarAlpha].CGColor); // dark teal
break;
default:
break;
}
}
CGContextRestoreGState(context);
// bottom stroke
CGContextSaveGState(context);
{
CGContextBeginPath(context);
CGContextMoveToPoint(context, 0, rect.size.height);
switch (_messageType) {
case GAMessageBarMessageTypeError:
CGContextSetRGBStrokeColor(context, 0.984f, 0.0f, 0.0f, 1.0f); // red
break;
case GAMessageBarMessageTypeSuccess:
CGContextSetRGBStrokeColor(context, 0.074f, 0.749f, 0.074f, 1.0f); // green
break;
case GAMessageBarMessageTypeInfo:
CGContextSetRGBStrokeColor(context, 0.007f, 0.686f, 0.737f, 1.0f); // teal
break;
case GAMessageBarMessageTypeLogo:
CGContextSetRGBStrokeColor(context, 0.007f, 0.686f, 0.737f, 1.0f); // teal
break;
default:
break;
}
CGContextSetLineWidth(context, 1.0);
CGContextAddLineToPoint(context, rect.size.width, rect.size.height);
CGContextStrokePath(context);
}
CGContextRestoreGState(context);
CGFloat xOffset = kGAMessageBarPadding;
CGFloat yOffset = kGAMessageBarPadding;
// icon
CGContextSaveGState(context);
{
switch (_messageType) {
case GAMessageBarMessageTypeError:
[[UIImage imageNamed:kGAImageIconNotificationWarning] drawInRect:CGRectMake(xOffset, yOffset, kGAMessageBarIconSize, kGAMessageBarIconSize)];
break;
case GAMessageBarMessageTypeSuccess:
[[UIImage imageNamed:kGAImageIconNotificationCheckmark] drawInRect:CGRectMake(xOffset, yOffset, kGAMessageBarIconSize, kGAMessageBarIconSize)];
break;
case GAMessageBarMessageTypeInfo:
[[UIImage imageNamed:kGAImageIconNotificationInfo] drawInRect:CGRectMake(xOffset, yOffset, kGAMessageBarIconSize, kGAMessageBarIconSize)];
break;
case GAMessageBarMessageTypeLogo:
[[UIImage imageNamed:kGAImageIconNotificationLogo] drawInRect:CGRectMake(xOffset, yOffset, kGAMessageBarIconSize, kGAMessageBarIconSize)];
break;
default:
break;
}
}
CGContextRestoreGState(context);
yOffset -= kGAMessageBarTextOffset;
xOffset += kGAMessageBarIconSize + kGAMessageBarPadding;
CGFloat maxWith = _button ? (rect.size.width - (kGAMessageBarPadding * 3) - ceil(kGAMessageBarPadding * 0.5) - kGAMessageBarIconSize) - kGAMessageBarButtonWidth : (rect.size.width - (kGAMessageBarPadding * 3) - kGAMessageBarIconSize);
CGSize titleLabelSize = [_titleString sizeWithFont:titleFont forWidth:maxWith lineBreakMode:UILineBreakModeTailTruncation];
if (_titleString && !_descriptionString){
yOffset = ceil(rect.size.height * 0.5) - ceil(titleLabelSize.height * 0.5) - kGAMessageBarTextOffset;
}
[shadowColor set];
[_titleString drawInRect:CGRectMake(xOffset, yOffset-1, titleLabelSize.width, titleLabelSize.height) withFont:titleFont lineBreakMode:UILineBreakModeTailTruncation alignment:UITextAlignmentLeft];
[titleColor set];
[_titleString drawInRect:CGRectMake(xOffset, yOffset, titleLabelSize.width, titleLabelSize.height) withFont:titleFont lineBreakMode:UILineBreakModeTailTruncation alignment:UITextAlignmentLeft];
yOffset += titleLabelSize.height;
CGSize descriptionLabelSize = [_descriptionString sizeWithFont:descriptionFont constrainedToSize:CGSizeMake(maxWith, kGAMessageBarMaxDescriptionHeight) lineBreakMode:UILineBreakModeTailTruncation];
[shadowColor set];
[_descriptionString drawInRect:CGRectMake(xOffset, yOffset-1, descriptionLabelSize.width, descriptionLabelSize.height) withFont:descriptionFont lineBreakMode:UILineBreakModeTailTruncation alignment:UITextAlignmentLeft];
[descriptionColor set];
[_descriptionString drawInRect:CGRectMake(xOffset, yOffset, descriptionLabelSize.width, descriptionLabelSize.height) withFont:descriptionFont lineBreakMode:UILineBreakModeTailTruncation alignment:UITextAlignmentLeft];
}
#pragma mark - Layout
- (void)layoutSubviews
{
[super layoutSubviews];
_shadowView.frame = CGRectMake(0, [self height], [self width], _shadowView.image.size.height);
_button.frame = CGRectMake(self.frame.size.width - kGAMessageBarButtonWidth - kGAMessageBarPadding, ceil(self.frame.size.height * 0.5) - ceil(kGAMessageBarButtonHeight * 0.5), kGAMessageBarButtonWidth, kGAMessageBarButtonHeight);
}
#pragma mark - Getters
- (CGFloat)height
{
if (_height == 0){
CGFloat maxWith = _button ? ([self width] - (kGAMessageBarPadding * 3) - ceil(kGAMessageBarPadding * 0.5) - kGAMessageBarIconSize) - kGAMessageBarButtonWidth : ([self width] - (kGAMessageBarPadding * 3) - kGAMessageBarIconSize);
CGSize titleLabelSize = [_titleString sizeWithFont:titleFont forWidth:maxWith lineBreakMode:UILineBreakModeTailTruncation];
CGSize descriptionLabelSize = [_descriptionString sizeWithFont:descriptionFont constrainedToSize:CGSizeMake(maxWith, 10000) lineBreakMode:UILineBreakModeTailTruncation];
_height = MAX((kGAMessageBarPadding*2) + titleLabelSize.height + descriptionLabelSize.height, (kGAMessageBarPadding*2) + kGAMessageBarIconSize);
}
return _height;
}
- (CGFloat)width
{
if (_width == 0){
_width = [UIScreen mainScreen].bounds.size.width;
}
return _width;
}
@end

View File

@@ -17,6 +17,13 @@
564982741741BF7A00077B8C /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 564982731741BF7A00077B8C /* Default-568h@2x.png */; };
569FCDF81741C09300F2B74C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 569FCDF41741C09300F2B74C /* AppDelegate.m */; };
569FCDF91741C09300F2B74C /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 569FCDF71741C09300F2B74C /* ViewController.m */; };
569FCDFD1741C34600F2B74C /* MessageBarManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 569FCDFC1741C34600F2B74C /* MessageBarManager.m */; };
56DE553117458A7B0026B7D2 /* icon-error.png in Resources */ = {isa = PBXBuildFile; fileRef = 56DE552B17458A7B0026B7D2 /* icon-error.png */; };
56DE553217458A7B0026B7D2 /* icon-error@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 56DE552C17458A7B0026B7D2 /* icon-error@2x.png */; };
56DE553317458A7B0026B7D2 /* icon-info.png in Resources */ = {isa = PBXBuildFile; fileRef = 56DE552D17458A7B0026B7D2 /* icon-info.png */; };
56DE553417458A7B0026B7D2 /* icon-info@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 56DE552E17458A7B0026B7D2 /* icon-info@2x.png */; };
56DE553517458A7B0026B7D2 /* icon-success.png in Resources */ = {isa = PBXBuildFile; fileRef = 56DE552F17458A7B0026B7D2 /* icon-success.png */; };
56DE553617458A7B0026B7D2 /* icon-success@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 56DE553017458A7B0026B7D2 /* icon-success@2x.png */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@@ -35,6 +42,16 @@
569FCDF41741C09300F2B74C /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
569FCDF61741C09300F2B74C /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
569FCDF71741C09300F2B74C /* ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
569FCDFB1741C34600F2B74C /* MessageBarManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MessageBarManager.h; sourceTree = "<group>"; };
569FCDFC1741C34600F2B74C /* MessageBarManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MessageBarManager.m; sourceTree = "<group>"; };
56DE552B17458A7B0026B7D2 /* icon-error.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-error.png"; sourceTree = "<group>"; };
56DE552C17458A7B0026B7D2 /* icon-error@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-error@2x.png"; sourceTree = "<group>"; };
56DE552D17458A7B0026B7D2 /* icon-info.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-info.png"; sourceTree = "<group>"; };
56DE552E17458A7B0026B7D2 /* icon-info@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-info@2x.png"; sourceTree = "<group>"; };
56DE552F17458A7B0026B7D2 /* icon-success.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-success.png"; sourceTree = "<group>"; };
56DE553017458A7B0026B7D2 /* icon-success@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-success@2x.png"; sourceTree = "<group>"; };
56DE553917458AB20026B7D2 /* StringConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StringConstants.h; sourceTree = "<group>"; };
56DE553A17458AB20026B7D2 /* UIConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIConstants.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -82,7 +99,10 @@
isa = PBXGroup;
children = (
569FCDF21741C09300F2B74C /* App Delegate */,
56DE553817458AB20026B7D2 /* Constants */,
569FCDF51741C09300F2B74C /* Controllers */,
569FCDFA1741C33700F2B74C /* Managers */,
56DE552917458A7B0026B7D2 /* Resources */,
564982641741BF7A00077B8C /* Supporting Files */,
);
path = MessageBarManagerDemo;
@@ -120,6 +140,45 @@
path = Controllers;
sourceTree = "<group>";
};
569FCDFA1741C33700F2B74C /* Managers */ = {
isa = PBXGroup;
children = (
569FCDFB1741C34600F2B74C /* MessageBarManager.h */,
569FCDFC1741C34600F2B74C /* MessageBarManager.m */,
);
name = Managers;
sourceTree = "<group>";
};
56DE552917458A7B0026B7D2 /* Resources */ = {
isa = PBXGroup;
children = (
56DE552A17458A7B0026B7D2 /* Icons */,
);
path = Resources;
sourceTree = "<group>";
};
56DE552A17458A7B0026B7D2 /* Icons */ = {
isa = PBXGroup;
children = (
56DE552B17458A7B0026B7D2 /* icon-error.png */,
56DE552C17458A7B0026B7D2 /* icon-error@2x.png */,
56DE552D17458A7B0026B7D2 /* icon-info.png */,
56DE552E17458A7B0026B7D2 /* icon-info@2x.png */,
56DE552F17458A7B0026B7D2 /* icon-success.png */,
56DE553017458A7B0026B7D2 /* icon-success@2x.png */,
);
path = Icons;
sourceTree = "<group>";
};
56DE553817458AB20026B7D2 /* Constants */ = {
isa = PBXGroup;
children = (
56DE553917458AB20026B7D2 /* StringConstants.h */,
56DE553A17458AB20026B7D2 /* UIConstants.h */,
);
path = Constants;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -175,6 +234,12 @@
564982701741BF7A00077B8C /* Default.png in Resources */,
564982721741BF7A00077B8C /* Default@2x.png in Resources */,
564982741741BF7A00077B8C /* Default-568h@2x.png in Resources */,
56DE553117458A7B0026B7D2 /* icon-error.png in Resources */,
56DE553217458A7B0026B7D2 /* icon-error@2x.png in Resources */,
56DE553317458A7B0026B7D2 /* icon-info.png in Resources */,
56DE553417458A7B0026B7D2 /* icon-info@2x.png in Resources */,
56DE553517458A7B0026B7D2 /* icon-success.png in Resources */,
56DE553617458A7B0026B7D2 /* icon-success@2x.png in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -188,6 +253,7 @@
5649826A1741BF7A00077B8C /* main.m in Sources */,
569FCDF81741C09300F2B74C /* AppDelegate.m in Sources */,
569FCDF91741C09300F2B74C /* ViewController.m in Sources */,
569FCDFD1741C34600F2B74C /* MessageBarManager.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@@ -8,6 +8,7 @@
#import "AppDelegate.h"
// Controllers
#import "ViewController.h"
@implementation AppDelegate

View File

@@ -0,0 +1,24 @@
//
// Constants.h
// MessageBarManagerDemo
//
// Created by Terry Worona on 5/16/13.
// Copyright (c) 2013 Terry Worona. All rights reserved.
//
#define localize(key, default) NSLocalizedStringWithDefaultValue(key, nil, [NSBundle mainBundle], default, nil)
#pragma mark - Message Bars
#define kStringMessageBarErrorTitle localize(@"message.bar.error.title", @"Error Title")
#define kStringMessageBarErrorMessage localize(@"message.bar.error.message", @"This is an error message!")
#define kStringMessageBarSuccessTitle localize(@"message.bar.success.title", @"Information Title")
#define kStringMessageBarSuccessMessage localize(@"message.bar.success.message", @"This is an info message!")
#define kStringMessageBarInfoTitle localize(@"message.bar.info.title", @"Information Title")
#define kStringMessageBarInfoMessage localize(@"message.bar.info.message", @"This is an info message!")
#pragma mark - Buttons
#define kStringButtonLabelSuccessMessage localize(@"button.label.success.message", @"Success Message")
#define kStringButtonLabelErrorMessage localize(@"button.label.error.message", @"Error Message")
#define kStringButtonLabelInfoMessage localize(@"button.label.info.message", @"Information Message")

View File

@@ -0,0 +1,13 @@
//
// Constants.h
// MessageBarManagerDemo
//
// Created by Terry Worona on 5/16/13.
// Copyright (c) 2013 Terry Worona. All rights reserved.
//
#pragma mark - Images
#define kImageIconSucces @"icon-success.png"
#define kImageIconError @"icon-error.png"
#define kImageIconInfo @"icon-info.png"

View File

@@ -8,22 +8,92 @@
#import "ViewController.h"
// Managers
#import "MessageBarManager.h"
// Constants
#import "StringConstants.h"
#define kViewControllerButtonPadding 10
#define kViewControllerButtonHeight 50
@interface ViewController ()
@property (nonatomic, strong) UIButton *errorButton;
@property (nonatomic, strong) UIButton *successButton;
@property (nonatomic, strong) UIButton *infoButton;
// Button presses
- (void)errorButtonPressed:(id)sender;
- (void)successButtonPressed:(id)sender;
- (void)infoButtonPressed:(id)sender;
@end
@implementation ViewController
- (void)viewDidLoad
@synthesize errorButton = _errorButton;
@synthesize successButton = _successButton;
@synthesize infoButton = _infoButton;
#pragma mark - View Lifecycle
- (void)loadView
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[super loadView];
self.view.backgroundColor = [UIColor whiteColor];
CGFloat xOffset = kViewControllerButtonPadding;
CGFloat yOffset = ceil(self.view.bounds.size.height * 0.5) - ceil(kViewControllerButtonHeight * 0.5);
_errorButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[_errorButton setTitle:kStringButtonLabelErrorMessage forState:UIControlStateNormal];
_errorButton.frame = CGRectMake(xOffset, yOffset, self.view.bounds.size.width - (xOffset*2), kViewControllerButtonHeight);
[_errorButton addTarget:self action:@selector(errorButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_errorButton];
yOffset = ceil(self.view.bounds.size.height * 0.5) - ceil(kViewControllerButtonHeight * 0.5) - kViewControllerButtonHeight - kViewControllerButtonPadding;
_successButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[_successButton setTitle:kStringButtonLabelSuccessMessage forState:UIControlStateNormal];
_successButton.frame = CGRectMake(xOffset, yOffset, self.view.bounds.size.width - (xOffset*2), kViewControllerButtonHeight);
[_successButton addTarget:self action:@selector(successButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_successButton];
yOffset = ceil(self.view.bounds.size.height * 0.5) - ceil(kViewControllerButtonHeight * 0.5) + kViewControllerButtonHeight + kViewControllerButtonPadding;
_infoButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[_infoButton setTitle:kStringButtonLabelInfoMessage forState:UIControlStateNormal];
_infoButton.frame = CGRectMake(xOffset, yOffset, self.view.bounds.size.width - (xOffset*2), kViewControllerButtonHeight);
[_infoButton addTarget:self action:@selector(infoButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_infoButton];
}
- (void)didReceiveMemoryWarning
#pragma mark - Button Presses
- (void)errorButtonPressed:(id)sender
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
[[MessageBarManager sharedInstance] showMessageWithTitle:kStringMessageBarErrorTitle
description:kStringMessageBarErrorMessage
type:MessageBarMessageTypeError callback:^{
NSLog(@"Message bar tapped!");
}];
}
- (void)successButtonPressed:(id)sender
{
[[MessageBarManager sharedInstance] showMessageWithTitle:kStringMessageBarSuccessTitle
description:kStringMessageBarSuccessMessage
type:MessageBarMessageTypeSuccess
forDuration:6.0];
}
- (void)infoButtonPressed:(id)sender
{
[[MessageBarManager sharedInstance] showMessageWithTitle:kStringMessageBarInfoTitle description:kStringMessageBarInfoMessage type:MessageBarMessageTypeInfo];
}
@end

View File

@@ -0,0 +1,37 @@
//
// MessageBarManager.h
//
// Created by Terry Worona on 5/13/13.
// Copyright (c) 2013 Terry Worona. All rights reserved.
//
#import <Foundation/Foundation.h>
typedef enum {
MessageBarMessageTypeError,
MessageBarMessageTypeSuccess,
MessageBarMessageTypeInfo
} MessageBarMessageType;
@interface MessageBarManager : NSObject
+ (MessageBarManager *)sharedInstance;
- (void)showMessageWithTitle:(NSString*)title description:(NSString*)description type:(MessageBarMessageType)type;
- (void)showMessageWithTitle:(NSString*)title description:(NSString*)description type:(MessageBarMessageType)type callback:(void (^)())callback;
- (void)showMessageWithTitle:(NSString*)title description:(NSString*)description type:(MessageBarMessageType)type forDuration:(CGFloat)duration;
- (void)showMessageWithTitle:(NSString*)title description:(NSString*)description type:(MessageBarMessageType)type forDuration:(CGFloat)duration callback:(void (^)())callback;
@end
@interface MessageBarStyleSheet : NSObject
// Colors (override for customization)
+ (UIColor*)backgroundColorForMessageType:(MessageBarMessageType)type;
+ (UIColor*)strokeColorForMessageType:(MessageBarMessageType)type;
// Icon images (override for customization)
+ (UIImage*)iconImageForMessageType:(MessageBarMessageType)type;
@end

View File

@@ -0,0 +1,404 @@
//
// MessageBarManager.m
//
// Created by Terry Worona on 5/13/13.
// Copyright (c) 2013 Terry Worona. All rights reserved.
//
#import "MessageBarManager.h"
// Quartz
#import <QuartzCore/QuartzCore.h>
// Delegate
#import "AppDelegate.h"
// Constants
#import "UIConstants.h"
#define kMessageBarAlpha 0.96
#define kMessageBarPadding 10
#define kMessageBarMaxDescriptionHeight 250
#define kMessageBarIconSize 36
#define kMessageBarDisplayDelay 3.0
#define kMessageBarTextOffset 2.0
#define kMessageBarAnimationDuration 0.25
@class MessageView;
@interface MessageView : UIView
@property (nonatomic, strong) NSString *titleString;
@property (nonatomic, strong) NSString *descriptionString;
@property (nonatomic, assign) MessageBarMessageType messageType;
@property (nonatomic, strong) UIImageView *shadowView;
@property (nonatomic, assign) BOOL hasCallback;
@property (nonatomic, strong) NSArray *callbacks;
@property (nonatomic, assign, getter = isHit) BOOL hit;
@property (nonatomic, assign, readonly) CGFloat height;
@property (nonatomic, assign, readonly) CGFloat width;
@property (nonatomic, assign) CGFloat duration;
- (id)initWithTitle:(NSString*)title description:(NSString*)description type:(MessageBarMessageType)type;
@end
@interface MessageBarManager ()
@property (nonatomic, strong) NSMutableArray *messageBarQueue;
@property (nonatomic, assign, getter = isMessageVisible) BOOL messageVisible;
@property (nonatomic, assign) CGFloat messageBarOffset;
+ (CGFloat)durationForMessageType:(MessageBarMessageType)messageType;
- (void)showNextMessage;
- (void)itemSelected:(UITapGestureRecognizer*)recognizer;
@end
@implementation MessageBarManager
@synthesize messageBarQueue = _messageBarQueue;
@synthesize messageVisible = _messageVisible;
@synthesize messageBarOffset = _messageBarOffset;
#pragma mark - Singleton
+ (MessageBarManager *)sharedInstance
{
static dispatch_once_t pred;
static MessageBarManager *instance = nil;
dispatch_once(&pred, ^{ instance = [[self alloc] init]; });
return instance;
}
#pragma mark - Static
+ (CGFloat)durationForMessageType:(MessageBarMessageType)messageType
{
return kMessageBarDisplayDelay;
}
#pragma mark - Alloc/Init
-(id)init
{
if(self = [super init]) {
_messageBarQueue = [[NSMutableArray alloc] init];
_messageVisible = NO;
_messageBarOffset = [[UIApplication sharedApplication] statusBarFrame].size.height;
}
return self;
}
#pragma mark - Public
- (void)showMessageWithTitle:(NSString*)title description:(NSString*)description type:(MessageBarMessageType)type
{
[self showMessageWithTitle:title description:description type:type forDuration:[MessageBarManager durationForMessageType:type] callback:nil];
}
- (void)showMessageWithTitle:(NSString*)title description:(NSString*)description type:(MessageBarMessageType)type callback:(void (^)())callback
{
[self showMessageWithTitle:title description:description type:type forDuration:[MessageBarManager durationForMessageType:type] callback:callback];
}
- (void)showMessageWithTitle:(NSString*)title description:(NSString*)description type:(MessageBarMessageType)type forDuration:(CGFloat)duration
{
[self showMessageWithTitle:title description:description type:type forDuration:duration callback:nil];
}
- (void)showMessageWithTitle:(NSString*)title description:(NSString*)description type:(MessageBarMessageType)type forDuration:(CGFloat)duration callback:(void (^)())callback
{
MessageView *messageView = [[MessageView alloc] initWithTitle:title description:description type:type];
messageView.callbacks = callback ? [NSArray arrayWithObject:callback] : [NSArray array];
messageView.hasCallback = callback ? YES : NO;
messageView.duration = duration;
messageView.hidden = YES;
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[delegate.window insertSubview:messageView atIndex:1];
[_messageBarQueue addObject:messageView];
if (!_messageVisible){
[self showNextMessage];
}
}
#pragma mark - Private
- (void)showNextMessage
{
if ([_messageBarQueue count] > 0){
_messageVisible = YES;
MessageView *messageView = [_messageBarQueue objectAtIndex:0];
messageView.frame = CGRectMake(0, -[messageView height], [messageView width], [messageView height]);
messageView.hidden = NO;
[messageView setNeedsDisplay];
UITapGestureRecognizer *gest = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(itemSelected:)];
[messageView addGestureRecognizer:gest];
if (messageView){
[_messageBarQueue removeObject:messageView];
[UIView animateWithDuration:kMessageBarAnimationDuration animations:^{
[messageView setFrame:CGRectMake(messageView.frame.origin.x, _messageBarOffset + messageView.frame.origin.y + [messageView height], [messageView width], [messageView height])]; // slide down
}];
[self performSelector:@selector(itemSelected:) withObject:messageView afterDelay:messageView.duration];
}
}
}
#pragma mark - Gestures
- (void)itemSelected:(id)sender
{
MessageView *messageView = nil;
BOOL itemHit = NO;
if ([sender isKindOfClass:[UIGestureRecognizer class]]){
messageView = (MessageView*)((UIGestureRecognizer*)sender).view;
itemHit = YES;
}
else if ([sender isKindOfClass:[MessageView class]]){
messageView = (MessageView*)sender;
}
if (messageView && ![messageView isHit]){
messageView.hit = YES;
[UIView animateWithDuration:kMessageBarAnimationDuration animations:^{
[messageView setFrame:CGRectMake(messageView.frame.origin.x, messageView.frame.origin.y - [messageView height] - _messageBarOffset, [messageView width], [messageView height])]; // slide back up
} completion:^(BOOL finished) {
_messageVisible = NO;
[messageView removeFromSuperview];
if (itemHit){
if ([messageView.callbacks count] > 0){
id obj = [messageView.callbacks objectAtIndex:0];
if (![obj isEqual:[NSNull null]]) {
((void (^)())obj)();
}
}
}
if([_messageBarQueue count] > 0) {
[self showNextMessage];
}
}];
}
}
@end
static UIFont *titleFont = nil;
static UIColor *titleColor = nil;
static UIFont *descriptionFont = nil;
static UIColor *descriptionColor = nil;
@implementation MessageView
@synthesize titleString = _titleString;
@synthesize descriptionString = _descriptionString;
@synthesize messageType = _messageType;
@synthesize shadowView = _shadowView;
@synthesize hasCallback = _hasCallback;
@synthesize callbacks = _callbacks;
@synthesize hit = _hit;
@synthesize width = _width;
@synthesize height = _height;
@synthesize duration = _duration;
#pragma mark - Alloc/Init
- (id)initWithTitle:(NSString*)title description:(NSString*)description type:(MessageBarMessageType)type
{
self = [super initWithFrame:CGRectZero];
if (self){
self.backgroundColor = [UIColor clearColor];
self.clipsToBounds = NO;
self.userInteractionEnabled = YES;
_titleString = title;
_descriptionString = description;
_messageType = type;
titleFont = [UIFont boldSystemFontOfSize:16.0];
titleColor = [UIColor colorWithWhite:1.0 alpha:1.0];
descriptionFont = [UIFont systemFontOfSize:14.0];
descriptionColor = [UIColor colorWithWhite:1.0 alpha:1.0];
_height = 0.0;
_width = 0.0;
_hasCallback = NO;
_hit = NO;
}
return self;
}
#pragma mark - Drawing
- (void)drawRect:(CGRect)rect
{
[super drawRect:rect];
CGContextRef context = UIGraphicsGetCurrentContext();
// background fill
CGContextSaveGState(context);
{
[[MessageBarStyleSheet backgroundColorForMessageType:_messageType] set];
CGContextFillRect(context, rect);
}
CGContextRestoreGState(context);
// bottom stroke
CGContextSaveGState(context);
{
CGContextBeginPath(context);
CGContextMoveToPoint(context, 0, rect.size.height);
CGContextSetStrokeColorWithColor(context, [MessageBarStyleSheet strokeColorForMessageType:_messageType].CGColor);
CGContextSetLineWidth(context, 1.0);
CGContextAddLineToPoint(context, rect.size.width, rect.size.height);
CGContextStrokePath(context);
}
CGContextRestoreGState(context);
CGFloat xOffset = kMessageBarPadding;
CGFloat yOffset = kMessageBarPadding;
// icon
CGContextSaveGState(context);
{
[[MessageBarStyleSheet iconImageForMessageType:_messageType] drawInRect:CGRectMake(xOffset, yOffset, kMessageBarIconSize, kMessageBarIconSize)];
}
CGContextRestoreGState(context);
yOffset -= kMessageBarTextOffset;
xOffset += kMessageBarIconSize + kMessageBarPadding;
CGFloat maxWith = (rect.size.width - (kMessageBarPadding * 3) - kMessageBarIconSize);
CGSize titleLabelSize = [_titleString sizeWithFont:titleFont forWidth:maxWith lineBreakMode:NSLineBreakByTruncatingTail];
if (_titleString && !_descriptionString){
yOffset = ceil(rect.size.height * 0.5) - ceil(titleLabelSize.height * 0.5) - kMessageBarTextOffset;
}
[titleColor set];
[_titleString drawInRect:CGRectMake(xOffset, yOffset, titleLabelSize.width, titleLabelSize.height) withFont:titleFont lineBreakMode:NSLineBreakByTruncatingTail alignment:NSTextAlignmentLeft];
yOffset += titleLabelSize.height;
CGSize descriptionLabelSize = [_descriptionString sizeWithFont:descriptionFont constrainedToSize:CGSizeMake(maxWith, kMessageBarMaxDescriptionHeight) lineBreakMode:NSLineBreakByTruncatingTail];
[descriptionColor set];
[_descriptionString drawInRect:CGRectMake(xOffset, yOffset, descriptionLabelSize.width, descriptionLabelSize.height) withFont:descriptionFont lineBreakMode:NSLineBreakByTruncatingTail alignment:NSTextAlignmentLeft];
}
#pragma mark - Layout
- (void)layoutSubviews
{
[super layoutSubviews];
_shadowView.frame = CGRectMake(0, [self height], [self width], _shadowView.image.size.height);
}
#pragma mark - Getters
- (CGFloat)height
{
if (_height == 0){
CGFloat maxWith = ([self width] - (kMessageBarPadding * 3) - kMessageBarIconSize);
CGSize titleLabelSize = [_titleString sizeWithFont:titleFont forWidth:maxWith lineBreakMode:NSLineBreakByTruncatingTail];
CGSize descriptionLabelSize = [_descriptionString sizeWithFont:descriptionFont constrainedToSize:CGSizeMake(maxWith, 10000) lineBreakMode:NSLineBreakByTruncatingTail];
_height = MAX((kMessageBarPadding*2) + titleLabelSize.height + descriptionLabelSize.height, (kMessageBarPadding*2) + kMessageBarIconSize);
}
return _height;
}
- (CGFloat)width
{
if (_width == 0){
_width = [UIScreen mainScreen].bounds.size.width;
}
return _width;
}
@end
@implementation MessageBarStyleSheet
#pragma mark - Colors
+ (UIColor*)backgroundColorForMessageType:(MessageBarMessageType)type
{
UIColor *backgroundColor = nil;
switch (type) {
case MessageBarMessageTypeError:
backgroundColor = [UIColor colorWithRed:1.0 green:0.611 blue:0.0 alpha:kMessageBarAlpha]; // orange
break;
case MessageBarMessageTypeSuccess:
backgroundColor = [UIColor colorWithRed:0.0f green:0.831f blue:0.176f alpha:kMessageBarAlpha]; // green
break;
case MessageBarMessageTypeInfo:
backgroundColor = [UIColor colorWithRed:0.0 green:0.482 blue:1.0 alpha:kMessageBarAlpha]; // blue
break;
default:
break;
}
return backgroundColor;
}
+ (UIColor*)strokeColorForMessageType:(MessageBarMessageType)type
{
UIColor *strokeColor = nil;
switch (type) {
case MessageBarMessageTypeError:
strokeColor = [UIColor colorWithRed:0.949f green:0.580f blue:0.0f alpha:1.0f]; // orange
break;
case MessageBarMessageTypeSuccess:
strokeColor = [UIColor colorWithRed:0.0f green:0.772f blue:0.164f alpha:1.0f]; // orange
break;
case MessageBarMessageTypeInfo:
strokeColor = [UIColor colorWithRed:0.0f green:0.415f blue:0.803f alpha:1.0f]; // orange
break;
default:
break;
}
return strokeColor;
}
+ (UIImage*)iconImageForMessageType:(MessageBarMessageType)type
{
UIImage *iconImage = nil;
switch (type) {
case MessageBarMessageTypeError:
iconImage = [UIImage imageNamed:kImageIconError];
break;
case MessageBarMessageTypeSuccess:
iconImage = [UIImage imageNamed:kImageIconSucces];
break;
case MessageBarMessageTypeInfo:
iconImage = [UIImage imageNamed:kImageIconInfo];
break;
default:
break;
}
return iconImage;
}
@end

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB