From 2fe42b62edda84f69574c082b5241a7d010f5a1f Mon Sep 17 00:00:00 2001 From: Robert Bu Date: Sun, 3 Jun 2012 18:42:58 +0800 Subject: [PATCH 1/2] Change to ARC mode; Add support for landscape mode; Add methods and properties to customize the notification view; Add support for iPad --- GKAchievementHandler.h | 15 +- GKAchievementHandler.m | 43 ++++-- GKAchievementNotification.h | 68 +++++++++ GKAchievementNotification.m | 297 +++++++++++++++++++++++++++--------- 4 files changed, 344 insertions(+), 79 deletions(-) mode change 100644 => 100755 GKAchievementHandler.h mode change 100644 => 100755 GKAchievementHandler.m mode change 100644 => 100755 GKAchievementNotification.h mode change 100644 => 100755 GKAchievementNotification.m diff --git a/GKAchievementHandler.h b/GKAchievementHandler.h old mode 100644 new mode 100755 index 73d2e74..87251b6 --- a/GKAchievementHandler.h +++ b/GKAchievementHandler.h @@ -20,7 +20,7 @@ */ @interface GKAchievementHandler : NSObject { - UIView *_topView; /**< Reference to top view of UIApplication. */ + UIWindow *_keyWindow; /**< Reference to top view of UIApplication. */ NSMutableArray *_queue; /**< Queue of achievement notifiers to display. */ UIImage *_image; /**< Logo to display in notifications. */ } @@ -47,4 +47,17 @@ */ - (void)notifyAchievementTitle:(NSString *)title andMessage:(NSString *)message; +/** + * Show an achievement notification with a message manually added. + * @param title The title of the achievement. + * @param message Description of the achievement. + * @param icon Icon of the achievement + */ +- (void)notifyAchievementTitleAndIcon:(NSString *)title andMessage:(NSString *)message withIcon:(UIImage*)icon; + +/** + * Show an user configured achievement notification + */ +- (void)notifyAchievementTitleAndIcon:(GKAchievementNotification*)notification; + @end diff --git a/GKAchievementHandler.m b/GKAchievementHandler.m old mode 100644 new mode 100755 index 192e5ca..5760bb5 --- a/GKAchievementHandler.m +++ b/GKAchievementHandler.m @@ -35,7 +35,13 @@ - (void)displayNotification:(GKAchievementNotification *)notification [notification setImage:nil]; } - [_topView addSubview:notification]; + /** when in landscape mode, adding notification view to the topview is the easiest way to get the nofitication displayed in landscape mode instead of setting view.transform manually */ + if(_keyWindow.rootViewController) { + [_keyWindow.rootViewController.view addSubview:notification]; + } + else { + [_keyWindow addSubview:notification]; + } [notification animateIn]; } @@ -60,7 +66,7 @@ - (id)init self = [super init]; if (self != nil) { - _topView = [[UIApplication sharedApplication] keyWindow]; + _keyWindow = [[UIApplication sharedApplication] keyWindow]; _queue = [[NSMutableArray alloc] initWithCapacity:0]; self.image = [UIImage imageNamed:@"gk-icon.png"]; } @@ -69,17 +75,16 @@ - (id)init - (void)dealloc { - [_queue release]; - [_image release]; - [super dealloc]; +// [_queue release]; +// [_image release]; + // [super dealloc]; } #pragma mark - - (void)notifyAchievement:(GKAchievementDescription *)achievement { - GKAchievementNotification *notification = [[[GKAchievementNotification alloc] initWithAchievementDescription:achievement] autorelease]; - notification.frame = kGKAchievementFrameStart; + GKAchievementNotification *notification = [[GKAchievementNotification alloc] initWithAchievementDescription:achievement]; notification.handlerDelegate = self; [_queue addObject:notification]; @@ -91,8 +96,7 @@ - (void)notifyAchievement:(GKAchievementDescription *)achievement - (void)notifyAchievementTitle:(NSString *)title andMessage:(NSString *)message { - GKAchievementNotification *notification = [[[GKAchievementNotification alloc] initWithTitle:title andMessage:message] autorelease]; - notification.frame = kGKAchievementFrameStart; + GKAchievementNotification *notification = [[GKAchievementNotification alloc] initWithTitle:title andMessage:message]; notification.handlerDelegate = self; [_queue addObject:notification]; @@ -102,6 +106,27 @@ - (void)notifyAchievementTitle:(NSString *)title andMessage:(NSString *)message } } +- (void)notifyAchievementTitleAndIcon:(NSString *)title andMessage:(NSString *)message withIcon:(UIImage*)icon { + GKAchievementNotification *notification = [[GKAchievementNotification alloc] initWithTitle:title andMessage:message]; + + notification.handlerDelegate = self; + [notification setImage:icon]; + + [_queue addObject:notification]; + if ([_queue count] == 1) + { + [self displayNotification:notification]; + } +} + +- (void)notifyAchievementTitleAndIcon:(GKAchievementNotification*)notification { + [_queue addObject:notification]; + if ([_queue count] == 1) + { + [self displayNotification:notification]; + } +} + #pragma mark - #pragma mark GKAchievementHandlerDelegate implementation diff --git a/GKAchievementNotification.h b/GKAchievementNotification.h old mode 100644 new mode 100755 index d25c2d9..4d9f4d4 --- a/GKAchievementNotification.h +++ b/GKAchievementNotification.h @@ -8,11 +8,19 @@ #import +@class GKAchievementDescription; + @class GKAchievementNotification; #define kGKAchievementAnimeTime 0.4f #define kGKAchievementDisplayTime 1.75f +#define kGKAchievementDefaultiPhoneSize CGSizeMake(284.f, 52.f); +#define kGKAchievementDefaultiPadSize CGSizeMake(426.f, 52.f); + +#define kGKAchievementDefaultBackground @"gk-notification.png" + +/* #define kGKAchievementDefaultSize CGRectMake(0.0f, 0.0f, 284.0f, 52.0f); #define kGKAchievementFrameStart CGRectMake(18.0f, -53.0f, 284.0f, 52.0f); #define kGKAchievementFrameEnd CGRectMake(18.0f, 10.0f, 284.0f, 52.0f); @@ -21,6 +29,7 @@ #define kGKAchievementText2 CGRectMake(10.0, 20.0f, 264.0f, 22.0f); #define kGKAchievementText1WLogo CGRectMake(45.0, 6.0f, 229.0f, 22.0f); #define kGKAchievementText2WLogo CGRectMake(45.0, 20.0f, 229.0f, 22.0f); +*/ #pragma mark - @@ -75,6 +84,28 @@ UILabel *_textLabel; /**< Text label used to display achievement title. */ UILabel *_detailLabel; /**< Text label used to display achievement description. */ + + CGPoint _position; /* center, automatically changes according to device orientation, normally you don't need to change this */ + CGSize _size; /* notification window size */ + + CGPoint _iconPosition; /* position of the icon */ + CGSize _iconSize; /* size of the icon, default = 34 * 34 */ + + CGPoint _titlePosition; /* position of the title */ + CGSize _titleSize; /* size of the title textbox, default = 229 * 22 */ + + CGPoint _descriptionPosition; /* position of the description */ + CGSize _descriptionSize; /* size of the description box, default = 229 * 22 */ + + /* + background image + */ + UIImage* _backgroundImage; + /* + Strech coordinates of the background image, + default (8.0f, 0.0f); + */ + CGPoint _backgroundStretch; id _handlerDelegate; /**< Reference to nofification handler. */ } @@ -96,6 +127,28 @@ /** Reference to nofification handler. */ @property (nonatomic, retain) id handlerDelegate; +/* notification position, automatically adjusted according to device orientation(center horizontally) */ +@property (nonatomic, readonly) CGPoint position; + +/* notification view size, changing this will also cause @iconSize, @titleSize and @descriptionSize to be adjusted automatically */ +@property (nonatomic, readonly) CGSize size; + + +@property (nonatomic, readwrite) CGSize iconSize; + +@property (nonatomic, readwrite) CGSize titleSize; +@property (nonatomic, readwrite) CGPoint titlePosition; + +@property (nonatomic, readwrite) CGSize descriptionSize; +@property (nonatomic, readwrite) CGPoint descriptionPosition; + + +/* position of the icon */ +@property (nonatomic, readwrite) CGPoint iconPosition; +@property (nonatomic, readwrite) CGPoint backgroundStrech; + +@property (nonatomic, readonly) UIImage* backgroundImage; + #pragma mark - /** @@ -129,4 +182,19 @@ */ - (void)setImage:(UIImage *)image; + +/** + * Set the position of the notification +*/ +- (void)setPosition:(CGPoint)position; +/** + * Set the size of the notification view + */ +- (void)setSize:(CGSize)size; + +/* + * Set the background image + */ +- (void)setBackgroundImage:(NSString*)background; + @end diff --git a/GKAchievementNotification.m b/GKAchievementNotification.m old mode 100644 new mode 100755 index be6d13c..0caccd9 --- a/GKAchievementNotification.m +++ b/GKAchievementNotification.m @@ -61,11 +61,41 @@ @implementation GKAchievementNotification @synthesize title=_title; @synthesize textLabel=_textLabel; +@synthesize position=_position; +@synthesize iconPosition=_iconPosition; +@synthesize size=_size; +@synthesize iconSize=_iconSize; +@synthesize titleSize=_titleSize; +@synthesize descriptionSize=_descriptionSize; +@synthesize backgroundStrech=_backgroundStretch; +@synthesize titlePosition=_titlePosition; +@synthesize descriptionPosition=_descriptionPosition; + +@synthesize backgroundImage=_backgroundImage; + #pragma mark - - (id)initWithAchievementDescription:(GKAchievementDescription *)achievement { - CGRect frame = kGKAchievementDefaultSize; + CGRect screen = [[UIScreen mainScreen] bounds]; + if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { + _size = kGKAchievementDefaultiPadSize; + } + else { + _size = kGKAchievementDefaultiPhoneSize; + } + + if(![self isLandscapeView]) { + _position.x = screen.size.width / 2 - _size.width / 2; + } else { + _position.x = screen.size.height / 2 - _size.width / 2; + } + + _position.y = 10.f; + CGRect frame = CGRectMake(_position.x, + _position.y, + _size.width, + _size.height); self.achievement = achievement; if ((self = [self initWithFrame:frame])) { @@ -75,10 +105,30 @@ - (id)initWithAchievementDescription:(GKAchievementDescription *)achievement - (id)initWithTitle:(NSString *)title andMessage:(NSString *)message { - CGRect frame = kGKAchievementDefaultSize; + CGRect screen = [[UIScreen mainScreen] bounds]; + + if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { + _size = kGKAchievementDefaultiPadSize; + } + else { + _size = kGKAchievementDefaultiPhoneSize; + } + + /* deal with landscape modes */ + if(![self isLandscapeView]) { + _position.x = screen.size.width / 2 - _size.width / 2; + } else { + _position.x = screen.size.height / 2 - _size.width / 2; + } + + _position.y = 10.f; + CGRect frame = CGRectMake(_position.x, + _position.y, + _size.width, + _size.height); self.title = title; self.message = message; - if ((self == [self initWithFrame:frame])) + if (self == [self initWithFrame:frame]) { } return self; @@ -88,61 +138,74 @@ - (id)initWithFrame:(CGRect)frame { if ((self = [super initWithFrame:frame])) { - // create the GK background - UIImage *backgroundStretch = [[UIImage imageNamed:@"gk-notification.png"] stretchableImageWithLeftCapWidth:8.0f topCapHeight:0.0f]; - UIImageView *tBackground = [[UIImageView alloc] initWithFrame:frame]; - tBackground.autoresizingMask = UIViewAutoresizingFlexibleWidth; - tBackground.image = backgroundStretch; - self.background = tBackground; - self.opaque = NO; - [tBackground release]; - [self addSubview:self.background]; - - CGRect r1 = kGKAchievementText1; - CGRect r2 = kGKAchievementText2; - - // create the text label - UILabel *tTextLabel = [[UILabel alloc] initWithFrame:r1]; - tTextLabel.textAlignment = UITextAlignmentCenter; - tTextLabel.backgroundColor = [UIColor clearColor]; - tTextLabel.textColor = [UIColor whiteColor]; - tTextLabel.font = [UIFont fontWithName:@"HelveticaNeue-Bold" size:15.0f]; - tTextLabel.text = NSLocalizedString(@"Achievement Unlocked", @"Achievemnt Unlocked Message"); - self.textLabel = tTextLabel; - [tTextLabel release]; - - // detail label - UILabel *tDetailLabel = [[UILabel alloc] initWithFrame:r2]; - tDetailLabel.textAlignment = UITextAlignmentCenter; - tDetailLabel.adjustsFontSizeToFitWidth = YES; - tDetailLabel.minimumFontSize = 10.0f; - tDetailLabel.backgroundColor = [UIColor clearColor]; - tDetailLabel.textColor = [UIColor whiteColor]; - tDetailLabel.font = [UIFont fontWithName:@"HelveticaNeue" size:11.0f]; - self.detailLabel = tDetailLabel; - [tDetailLabel release]; - - if (self.achievement) + _iconPosition = CGPointMake(7.0f, 6.0f); + _iconSize = CGSizeMake(34.f, 34.f); + + _titlePosition = CGPointMake(10.f, 6.f); + _titleSize = CGSizeMake(_size.width - _titlePosition.x * 2, + 22.f); + + _descriptionPosition = CGPointMake(10.f, 20.f); + _descriptionSize = CGSizeMake(_size.width - _titlePosition.x * 2, + 22.f); + + _backgroundStretch = CGPointMake(8.0f, 0.f); + } + return self; +} + +- (void)setupContent { + [self setBackgroundImage:kGKAchievementDefaultBackground]; + + CGRect r1 = CGRectMake(_titlePosition.x, + _titlePosition.y, + _titleSize.width, + _titleSize.height); + CGRect r2 = CGRectMake(_descriptionPosition.x, + _descriptionPosition.y, + _descriptionSize.width, + _descriptionSize.height); + + // create the text label + UILabel *tTextLabel = [[UILabel alloc] initWithFrame:r1]; + tTextLabel.textAlignment = UITextAlignmentCenter; + tTextLabel.backgroundColor = [UIColor clearColor]; + tTextLabel.textColor = [UIColor whiteColor]; + tTextLabel.font = [UIFont fontWithName:@"HelveticaNeue-Bold" size:15.0f]; + tTextLabel.text = NSLocalizedString(@"Achievement Unlocked", @"Achievemnt Unlocked Message"); + self.textLabel = tTextLabel; + // [tTextLabel release]; + + // detail label + UILabel *tDetailLabel = [[UILabel alloc] initWithFrame:r2]; + tDetailLabel.textAlignment = UITextAlignmentCenter; + tDetailLabel.adjustsFontSizeToFitWidth = YES; + tDetailLabel.minimumFontSize = 10.0f; + tDetailLabel.backgroundColor = [UIColor clearColor]; + tDetailLabel.textColor = [UIColor whiteColor]; + tDetailLabel.font = [UIFont fontWithName:@"HelveticaNeue" size:11.0f]; + self.detailLabel = tDetailLabel; + // [tDetailLabel release]; + + if (self.achievement) + { + self.textLabel.text = self.achievement.title; + self.detailLabel.text = self.achievement.achievedDescription; + } + else + { + if (self.title) { - self.textLabel.text = self.achievement.title; - self.detailLabel.text = self.achievement.achievedDescription; + self.textLabel.text = self.title; } - else + if (self.message) { - if (self.title) - { - self.textLabel.text = self.title; - } - if (self.message) - { - self.detailLabel.text = self.message; - } + self.detailLabel.text = self.message; } - - [self addSubview:self.textLabel]; - [self addSubview:self.detailLabel]; } - return self; + + [self addSubview:self.textLabel]; + [self addSubview:self.detailLabel]; } - (void)dealloc @@ -152,15 +215,15 @@ - (void)dealloc self.handlerDelegate = nil; self.logo = nil; - [_achievement release]; - [_background release]; - [_detailLabel release]; - [_logo release]; - [_message release]; - [_textLabel release]; - [_title release]; +// [_achievement release]; +// [_background release]; + // [_detailLabel release]; +// [_logo release]; +// [_message release]; +// [_textLabel release]; +// [_title release]; - [super dealloc]; +// [super dealloc]; } @@ -168,13 +231,28 @@ - (void)dealloc - (void)animateIn { + /* first setup contents with configuration */ + [self setupContent]; + + self.frame = CGRectMake(_position.x, + -self.size.height - 1, + _size.width, + _size.height); + [self delegateCallback:@selector(willShowAchievementNotification:) withObject:self]; [UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:kGKAchievementAnimeTime]; [UIView setAnimationDelegate:self]; [UIView setAnimationBeginsFromCurrentState:YES]; [UIView setAnimationDidStopSelector:@selector(animationInDidStop:finished:context:)]; - self.frame = kGKAchievementFrameEnd; + + [self shouldAutorotateToInterfaceOrientation:[[UIApplication sharedApplication] statusBarOrientation]]; + + + self.frame = CGRectMake(_position.x, + _position.y, + _size.width, + _size.height); [UIView commitAnimations]; } @@ -186,25 +264,50 @@ - (void)animateOut [UIView setAnimationDelegate:self]; [UIView setAnimationBeginsFromCurrentState:YES]; [UIView setAnimationDidStopSelector:@selector(animationOutDidStop:finished:context:)]; - self.frame = kGKAchievementFrameStart; + self.frame = CGRectMake(_position.x, + -self.size.height - 1, + _size.width, + _size.height); [UIView commitAnimations]; } +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { + return YES; +} + - (void)setImage:(UIImage *)image { if (image) { if (!self.logo) { - UIImageView *tLogo = [[UIImageView alloc] initWithFrame:CGRectMake(7.0f, 6.0f, 34.0f, 34.0f)]; + UIImageView *tLogo = [[UIImageView alloc] initWithFrame:CGRectMake(_iconPosition.x, + _iconPosition.y, + _iconSize.width, + _iconSize.height)]; tLogo.contentMode = UIViewContentModeCenter; self.logo = tLogo; - [tLogo release]; + // [tLogo release]; [self addSubview:self.logo]; } self.logo.image = image; - self.textLabel.frame = kGKAchievementText1WLogo; - self.detailLabel.frame = kGKAchievementText2WLogo; + + _titlePosition = CGPointMake(10.f + _iconSize.width + _iconPosition.x, 6.f); + _titleSize = CGSizeMake(_size.width - _titlePosition.x - 10.f, + 22.f); + + _descriptionPosition = CGPointMake(10.f + _iconSize.width + _iconPosition.x, 20.f); + _descriptionSize = CGSizeMake(_size.width - _titlePosition.x - 10.f, + 22.f); + + self.textLabel.frame = CGRectMake(_titlePosition.x, + _titlePosition.y, + _titleSize.width, + _titleSize.height);; + self.detailLabel.frame = CGRectMake(_descriptionPosition.x, + _descriptionPosition.y, + _descriptionSize.width, + _descriptionSize.height);; } else { @@ -212,9 +315,65 @@ - (void)setImage:(UIImage *)image { [self.logo removeFromSuperview]; } - self.textLabel.frame = kGKAchievementText1; - self.detailLabel.frame = kGKAchievementText2; + + _titlePosition = CGPointMake(10.f, 6.f); + _titleSize = CGSizeMake(_size.width - _titlePosition.x - 10.f, + 22.f); + + _descriptionPosition = CGPointMake(10.f, 20.f); + _descriptionSize = CGSizeMake(_size.width - _titlePosition.x - 10.f, + 22.f); + + self.textLabel.frame = CGRectMake(_titlePosition.x, + _titlePosition.y, + _titleSize.width, + _titleSize.height); + self.detailLabel.frame = CGRectMake(_descriptionPosition.x, + _descriptionPosition.y, + _descriptionSize.width, + _descriptionSize.height); } } +- (BOOL)isLandscapeView { + UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; + return orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight; +} + +- (void)setPosition:(CGPoint)position { + _position = position; +} + +- (void)setIconSize:(CGSize)iconSize { + _iconSize = iconSize; + if(_size.height < iconSize.height) + _size.height = _iconSize.height + 18.f; +} + +- (void)setSize:(CGSize)size { + _size = size; + + _titlePosition = CGPointMake(10.f, 6.f); + _titleSize = CGSizeMake(_size.width - _titlePosition.x * 2, + 22.f); + + _descriptionPosition = CGPointMake(10.f, 20.f); + _descriptionSize = CGSizeMake(_size.width - _titlePosition.x * 2, + 22.f); +} + +- (void)setBackgroundImage:(NSString *)background { + _backgroundImage = [[UIImage imageNamed:background] stretchableImageWithLeftCapWidth:_backgroundStretch.x topCapHeight:_backgroundStretch.y]; + UIImageView *tBackground = [[UIImageView alloc] initWithFrame: CGRectMake(0.f, + 0.f, + _size.width, + _size.height)]; + tBackground.autoresizingMask = UIViewAutoresizingFlexibleWidth; + tBackground.image = _backgroundImage; + self.background = tBackground; + self.opaque = NO; + // [tBackground release]; + [self addSubview:self.background]; +} + @end From 23a6c18f7c11921683028e23484679b9232f0e63 Mon Sep 17 00:00:00 2001 From: Dominik Hadl Date: Sun, 5 May 2013 14:04:39 +0200 Subject: [PATCH 2/2] Fixed ARC and accessor warnings --- GKAchievementNotification.h | 2 +- GKAchievementNotification.m | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/GKAchievementNotification.h b/GKAchievementNotification.h index 4d9f4d4..4f6cbfc 100755 --- a/GKAchievementNotification.h +++ b/GKAchievementNotification.h @@ -195,6 +195,6 @@ /* * Set the background image */ -- (void)setBackgroundImage:(NSString*)background; +- (void)setCustomBackgroundImage:(NSString*)background; @end diff --git a/GKAchievementNotification.m b/GKAchievementNotification.m index 0caccd9..9b1b4d2 100755 --- a/GKAchievementNotification.m +++ b/GKAchievementNotification.m @@ -41,7 +41,10 @@ - (void)delegateCallback:(SEL)selector withObject:(id)object { if ([self.handlerDelegate respondsToSelector:selector]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" [self.handlerDelegate performSelector:selector withObject:object]; +#pragma clang diagnostic pop } } } @@ -155,7 +158,7 @@ - (id)initWithFrame:(CGRect)frame } - (void)setupContent { - [self setBackgroundImage:kGKAchievementDefaultBackground]; + [self setCustomBackgroundImage:kGKAchievementDefaultBackground]; CGRect r1 = CGRectMake(_titlePosition.x, _titlePosition.y, @@ -362,7 +365,7 @@ - (void)setSize:(CGSize)size { 22.f); } -- (void)setBackgroundImage:(NSString *)background { +- (void)setCustomBackgroundImage:(NSString *)background { _backgroundImage = [[UIImage imageNamed:background] stretchableImageWithLeftCapWidth:_backgroundStretch.x topCapHeight:_backgroundStretch.y]; UIImageView *tBackground = [[UIImageView alloc] initWithFrame: CGRectMake(0.f, 0.f,