30 #import "Toast+UIView.h"
31 #import <QuartzCore/QuartzCore.h>
32 #import <objc/runtime.h>
35 #define kMaxHeight 0.8
37 #define kHorizontalPadding 10.0
38 #define kVerticalPadding 10.0
39 #define kCornerRadius 10.0
41 #define kFontSize 16.0
42 #define kMaxTitleLines 999
43 #define kMaxMessageLines 999
45 #define kFadeDuration 0.2
47 #define kDefaultLength 3
48 #define kDefaultPosition @"bottom"
50 #define kImageWidth 80.0
51 #define kImageHeight 80.0
53 static NSString *kDurationKey =
@"duration";
55 @interface UIView (ToastPrivate)
57 - (CGPoint)getPositionFor:(
id)position toast:(UIView *)toast;
58 - (UIView *)makeViewForMessage:(NSString *)message title:(NSString *)title image:(UIImage *)image;
65 #pragma mark Toast Methods
67 - (void)makeToast:(NSString *)message
69 [
self makeToast:message duration:kDefaultLength position:kDefaultPosition];
72 - (void)makeToast:(NSString *)message duration:(
float)interval position:(
id)point
74 UIView *toast = [
self makeViewForMessage:message title:nil image:nil];
75 [
self showToast:toast duration:interval position:point];
78 - (void)makeToast:(NSString *)message
79 duration:(
float)interval
81 title:(NSString *)title
83 UIView *toast = [
self makeViewForMessage:message title:title image:nil];
84 [
self showToast:toast duration:interval position:point];
87 - (void)makeToast:(NSString *)message
88 duration:(
float)interval
90 image:(UIImage *)image
92 UIView *toast = [
self makeViewForMessage:message title:nil image:image];
93 [
self showToast:toast duration:interval position:point];
96 - (void)makeToast:(NSString *)message
97 duration:(
float)interval
99 title:(NSString *)title
100 image:(UIImage *)image
102 UIView *toast = [
self makeViewForMessage:message title:title image:image];
103 [
self showToast:toast duration:interval position:point];
106 - (void)showToast:(UIView *)toast
108 [
self showToast:toast duration:kDefaultLength position:kDefaultPosition];
111 - (void)showToast:(UIView *)toast duration:(
float)interval position:(
id)point
120 CGPoint toastPoint = [
self getPositionFor:point toast:toast];
123 objc_setAssociatedObject(toast, &kDurationKey, [NSNumber numberWithFloat:interval],
124 OBJC_ASSOCIATION_RETAIN);
126 [toast setCenter:toastPoint];
127 [toast setAlpha:0.0];
128 [
self addSubview:toast];
130 [UIView beginAnimations:@"fade_in" context:toast];
131 [UIView setAnimationDuration:kFadeDuration];
132 [UIView setAnimationDelegate:self];
133 [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
134 [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
135 [toast setAlpha:1.0];
136 [UIView commitAnimations];
140 #pragma mark Animation Delegate Method
142 - (void)animationDidStop:(NSString *)animationID finished:(BOOL)finished context:(
void *)context
145 UIView *toast = (UIView *)context;
148 float interval = [(NSNumber *)objc_getAssociatedObject(toast, &kDurationKey) floatValue];
150 if ([animationID isEqualToString:
@"fade_in"])
153 [UIView beginAnimations:@"fade_out" context:toast];
154 [UIView setAnimationDelay:interval];
155 [UIView setAnimationDuration:kFadeDuration];
156 [UIView setAnimationDelegate:self];
157 [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
158 [UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
159 [toast setAlpha:0.0];
160 [UIView commitAnimations];
162 else if ([animationID isEqualToString:
@"fade_out"])
165 [toast removeFromSuperview];
170 #pragma mark Private Methods
172 - (CGPoint)getPositionFor:(
id)point toast:(UIView *)toast
182 if ([point isKindOfClass:[NSString
class]])
185 if ([point caseInsensitiveCompare:
@"top"] == NSOrderedSame)
187 return CGPointMake(
self.bounds.size.width / 2,
188 (toast.frame.size.height / 2) + kVerticalPadding);
190 else if ([point caseInsensitiveCompare:
@"bottom"] == NSOrderedSame)
192 return CGPointMake(
self.bounds.size.width / 2,
193 (
self.bounds.size.height - (toast.frame.size.height / 2)) -
196 else if ([point caseInsensitiveCompare:
@"center"] == NSOrderedSame)
198 return CGPointMake(
self.bounds.size.width / 2,
self.bounds.size.height / 2);
201 else if ([point isKindOfClass:[NSValue
class]])
203 return [point CGPointValue];
206 NSLog(
@"Error: Invalid position for toast.");
207 return [
self getPositionFor:kDefaultPosition toast:toast];
210 - (UIView *)makeViewForMessage:(NSString *)message title:(NSString *)title image:(UIImage *)image
219 if ((message == nil) && (title == nil) && (image == nil))
222 UILabel *messageLabel = nil;
223 UILabel *titleLabel = nil;
224 UIImageView *imageView = nil;
227 UIView *wrapperView = [[[UIView alloc] init] autorelease];
228 [wrapperView.layer setCornerRadius:kCornerRadius];
229 [wrapperView setBackgroundColor:[[UIColor blackColor] colorWithAlphaComponent:kOpacity]];
230 wrapperView.autoresizingMask =
231 UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin |
232 UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
236 imageView = [[[UIImageView alloc] initWithImage:image] autorelease];
237 [imageView setContentMode:UIViewContentModeScaleAspectFit];
239 setFrame:CGRectMake(kHorizontalPadding, kVerticalPadding, kImageWidth, kImageHeight)];
242 float imageWidth, imageHeight, imageLeft;
245 if (imageView != nil)
247 imageWidth = imageView.bounds.size.width;
248 imageHeight = imageView.bounds.size.height;
249 imageLeft = kHorizontalPadding;
253 imageWidth = imageHeight = imageLeft = 0;
258 titleLabel = [[[UILabel alloc] init] autorelease];
259 [titleLabel setNumberOfLines:kMaxTitleLines];
260 [titleLabel setFont:[UIFont boldSystemFontOfSize:kFontSize]];
261 [titleLabel setTextAlignment:UITextAlignmentLeft];
262 [titleLabel setLineBreakMode:UILineBreakModeWordWrap];
263 [titleLabel setTextColor:[UIColor whiteColor]];
264 [titleLabel setBackgroundColor:[UIColor clearColor]];
265 [titleLabel setAlpha:1.0];
266 [titleLabel setText:title];
269 CGSize maxSizeTitle = CGSizeMake((
self.bounds.size.width * kMaxWidth) - imageWidth,
270 self.bounds.size.height * kMaxHeight);
271 CGSize expectedSizeTitle = [title sizeWithFont:titleLabel.font
272 constrainedToSize:maxSizeTitle
273 lineBreakMode:titleLabel.lineBreakMode];
274 [titleLabel setFrame:CGRectMake(0, 0, expectedSizeTitle.width, expectedSizeTitle.height)];
279 messageLabel = [[[UILabel alloc] init] autorelease];
280 [messageLabel setNumberOfLines:kMaxMessageLines];
281 [messageLabel setFont:[UIFont systemFontOfSize:kFontSize]];
282 [messageLabel setLineBreakMode:UILineBreakModeWordWrap];
283 [messageLabel setTextColor:[UIColor whiteColor]];
284 [messageLabel setTextAlignment:UITextAlignmentCenter];
285 [messageLabel setBackgroundColor:[UIColor clearColor]];
286 [messageLabel setAlpha:1.0];
287 [messageLabel setText:message];
290 CGSize maxSizeMessage = CGSizeMake((
self.bounds.size.width * kMaxWidth) - imageWidth,
291 self.bounds.size.height * kMaxHeight);
292 CGSize expectedSizeMessage = [message sizeWithFont:messageLabel.font
293 constrainedToSize:maxSizeMessage
294 lineBreakMode:messageLabel.lineBreakMode];
296 setFrame:CGRectMake(0, 0, expectedSizeMessage.width, expectedSizeMessage.height)];
300 float titleWidth, titleHeight, titleTop, titleLeft;
302 if (titleLabel != nil)
304 titleWidth = titleLabel.bounds.size.width;
305 titleHeight = titleLabel.bounds.size.height;
306 titleTop = kVerticalPadding;
307 titleLeft = imageLeft + imageWidth + kHorizontalPadding;
311 titleWidth = titleHeight = titleTop = titleLeft = 0;
315 float messageWidth, messageHeight, messageLeft, messageTop;
317 if (messageLabel != nil)
319 messageWidth = messageLabel.bounds.size.width;
320 messageHeight = messageLabel.bounds.size.height;
321 messageLeft = imageLeft + imageWidth + kHorizontalPadding;
322 messageTop = titleTop + titleHeight + kVerticalPadding;
326 messageWidth = messageHeight = messageLeft = messageTop = 0;
331 float longerWidth = (messageWidth < titleWidth) ? titleWidth : messageWidth;
332 float longerLeft = (messageLeft < titleLeft) ? titleLeft : messageLeft;
337 ((longerLeft + longerWidth + kHorizontalPadding) < imageWidth + (kHorizontalPadding * 2))
338 ? imageWidth + (kHorizontalPadding * 2)
339 : (longerLeft + longerWidth + kHorizontalPadding);
340 float wrapperHeight =
341 ((messageTop + messageHeight + kVerticalPadding) < imageHeight + (kVerticalPadding * 2))
342 ? imageHeight + (kVerticalPadding * 2)
343 : (messageTop + messageHeight + kVerticalPadding);
345 [wrapperView setFrame:CGRectMake(0, 0, wrapperWidth, wrapperHeight)];
347 if (titleLabel != nil)
349 [titleLabel setFrame:CGRectMake(titleLeft, titleTop, titleWidth, titleHeight)];
350 [wrapperView addSubview:titleLabel];
353 if (messageLabel != nil)
355 [messageLabel setFrame:CGRectMake(messageLeft, messageTop, messageWidth, messageHeight)];
356 [wrapperView addSubview:messageLabel];
359 if (imageView != nil)
361 [wrapperView addSubview:imageView];