Good morning / afternoon / evening / night% username%!
Prehistory
In the process of implementing the next
project , it became necessary to implement an effective notification of the user about something (for example, the absence of an Internet connection). So how do you do this? The standard UIAlertView class turned out to be too cumbersome and boring for this purpose, and, finding nothing more suitable, it was decided to write
my casino with blackjack ... its own alert class.
Implementation
So let's get started. The main criterion for this class was “calling with one line of code,” so I got the method:
+ (void) showMessage:(NSString *)message;
')
Based on the task of “very simple user notification”, it was decided to use:
- UILabel - 1 pc.
- UIView - 2pcs.
For a start, we will take the UILabel and "sharpen" for our needs:
UILabel *messageLabel = [[UILabel alloc] init]; messageLabel.textAlignment = UITextAlignmentCenter; messageLabel.numberOfLines = 0; messageLabel.lineBreakMode = UILineBreakModeWordWrap; messageLabel.text = message; messageLabel.font = [UIFont fontWithName:@”Helvetica-Bold” size:15.0f]; messageLabel.textColor = [UIColor whiteColor]; messageLabel.backgroundColor = [UIColor clearColor];
Next you need to know - "And how much will our message take up space on the screen?"
CGSize messageSize = [message sizeWithFont:messageLabel.font constrainedToSize:CGSizeMake(160.0f, 9999.0f) lineBreakMode:UILineBreakModeWordWrap];
Method for NSString sizeWithFont: (UIFont *) font constrainedToSize (CGSize) size lineBreakMode: (UILineBreakMode) lineBreakMode will return to us in this case the size of the rectangle in which the text will be entered based on the conditions:
- multiline
- the width of the block is 160.0f (may be larger if the word does not fit into this size)
Further it is necessary to make a rectangle from the obtained sizes taking into account 2 additional sizes:
- The thickness of the border of the parent element (in it we "put" UILabel)
- Indent from parental boundaries
CGRect messageRect = CGRectMake(offsetSize.width + borderWidth, offsetSize.height + borderWidth, messageSize.width, messageSize.height); messageLabel.frame = messageRect;
Everything, on it meanwhile we finished with UILabel.
Next in line is the container for UILabel - the first of two UIViews. For the container it was necessary to take into account - the background color, border, indents from the border. As an addition to the design of the annotation - rounded corners, shadow and transparency. Below is the code for our container.
messageSize.width += offsetSize.width*2.0f + borderWidth; messageSize.height += offsetSize.height*2.0f + borderWidth; contentRect = CGRectMake(0.0f, 0.0f, messageSize.width, messageSize.height); UIView *content = [[UIView alloc] init]; content.frame = contentRect; content.backgroundColor = [UIColor colorWithRed:(60.0f/255.0f) green:(60.0f/255.0f) blue:(60.0f/255.0f) alpha:1.0f]; content.alpha = 0.8f; content.layer.cornerRadius = 8.0f; content.layer.shadowRadius = 8.0f; content.layer.masksToBounds = NO; content.layer.shadowOffset = CGSizeMake(0.0f, 4.0f); content.layer.shadowOpacity = 1.0f; content.layer.borderWidth = 1.0f; content.layer.borderColor = [[UIColor colorWithRed:(128.0f/255.0f) green:(128.0f/255.0f) blue:(128.0f/255.0f) alpha:1.0f] CGColor]; content.layer.shadowPath = [UIBezierPath bezierPathWithRect:contentRect].CGPath;
That's all. Now we can only use the last remaining UIView - rootView. We will use it for animation.
UIView *rootView = [[UIView alloc] init]; rootView.tag = 2000; rootView.frame = contentRect; rootView.alpha = 0.0f;
Everything at this stage we have prepared for further use UILabel with the message and 2 UIView containers. It remains only to assemble a matryoshka from them and establish a position in the center of the screen:
messageLabel.center = CGPointMake(contentRect.size.width/2.0f, contentRect.size.height/2.0f); [content addSubview:messageLabel]; [messageLabel release]; [rootView addSubview:content]; [content release]; rootView.center = [[UIApplication sharedApplication] keyWindow].center;
Animation
In our case, the animation was divided into 3 components:
- Appearance
- Bounce effect imitation
- Disappearance
The bounce effect was achieved by simply animating the rootView increase from the size with a factor of 0.8 to the size of a factor of 1.1 and an immediate decrease to the natural size - a factor of 1.0. Appearance and Disappearance - change rootView.alpha from 0.0f to 1.0f and vice versa. The disappearance is also accompanied by a change in size to a factor of 1.2. For the appearance and achievement of the “peak” point of the bounce-effect (namely, when the coefficient of 1.2 is reached), it was decided to allocate 2/3 of the total time scheduled for the animation. The remainder of the time was used to go to the normal display. Then the user is given time to be able to read the message and then the message disappears.
Starting with iOS version 4.0, animation is implemented through blocks. Therefore, the required version of iOS is not lower than 4.0 (in the future we plan to add support for iOS 3).
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion
the UIView class method allows us to set:
- animation duration
- the duration of the pause before the animation
- animation settings
- directly to the animation itself
- and the code that will be executed upon completion of the animation
The animation implementation code is shown below:
rootView.transform = CGAffineTransformMakeScale(0.8f, 0.8f); [[[UIApplication sharedApplication] keyWindow] addSubview:rootView]; [UIView animateWithDuration:0.35*0.66 delay:0.0 options:UIViewAnimationCurveEaseOut animations:^ { rootView.alpha = 0.66f; rootView.transform = CGAffineTransformMakeScale(1.1f, 1.1f); } completion:^(BOOL completed) { [UIView animateWithDuration:0.35*0.33 delay:0.0 options:UIViewAnimationCurveLinear animations:^{ rootView.alpha = 1.0f; rootView.transform = CGAffineTransformIdentity; } completion:^(BOOL completed) { [UIView animateWithDuration:0.35 delay:0.9 options:UIViewAnimationCurveEaseIn animations:^{ rootView.alpha = 0.0f; rootView.transform = CGAffineTransformMakeScale(1.2f, 1.2f); } completion:^(BOOL completed) { [rootView removeFromSuperview]; [rootView release]; }]; }]; }];
Total
As a result of writing this class, we got a very convenient “alert” that can be called up with a single line of code:
[FHNotification showMessage:@”Very simple inApp-notification”];
findings
Advantages of this class:
- Very very simple class to use.
Minuses:
Only iOS 4.0+ support- Text alert only option
QuartzCore.framework is also required for this class.
The source code can be downloaded on
github , slightly updated and extended.
That's all. Thanks for attention