UILabel animating frame change disregarding delay - objective-c

I have a UILabel that I show / hide. I want to show the label, pause for a few seconds and hide it. This code ISN'T working. It removes the view as soon as the animation finished (instantly)
-(void) show
{
[UIView animateWithDuration:.5f delay:0.0f
options:UIViewAnimationOptionCurveEaseIn animations:^{
CGRect newFrame = CGRectMake(0.0f, 64.0f, [UIScreen mainScreen].bounds.size.width, 44.0f);
self.frame = newFrame;
} completion:^(BOOL finished){
[self hideAndRemove];
}];
}
-(void) hideAndRemove
{
[UIView animateWithDuration:.5f delay:2.0f
options:UIViewAnimationOptionCurveEaseIn animations:^{
CGRect frame = CGRectMake(0.0f, 64.0f, [UIScreen mainScreen].bounds.size.width, 0.0f);
self.frame = frame;
} completion:^(BOOL finished){
// nothing
}];
}
However, if I try some other animation on the frame, the delay works and the frame change is animated:
-(void) show
{
[UIView animateWithDuration:.5f delay:0.0f
options:UIViewAnimationOptionCurveEaseIn animations:^{
CGRect newFrame = CGRectMake(0.0f, 64.0f, [UIScreen mainScreen].bounds.size.width, 44.0f);
self.frame = newFrame;
} completion:^(BOOL finished){
[self hideAndRemove];
}];
}
-(void) hideAndRemove
{
[UIView animateWithDuration:.5f delay:2.0f
options:UIViewAnimationOptionCurveEaseIn animations:^{
CGRect frame = CGRectMake(0.0f, 64.0f, [UIScreen mainScreen].bounds.size.width, 250.0f);
self.frame = frame;
} completion:^(BOOL finished){
// nothing
}];
}

I don't know what the problem might be, but I think it comes from the frame height who shouldn't be set to 0.
Why not using [UILabel setAlpha:0] to hide your label, and [UILabel setAlpha:1] to show it back ? It seems cleaner than changing its frame height to 0, and it animates nicely.

Related

Repeating glow animation outside radius (like bulb glowing effect)

I am working on iPad project and I need to do animation like glowing bulb with smooth ON/ OFF effect. How can I achieve this?
I tried with UIView animation and try to get same kind of animation.
Here is code which I tried.
-(void) setGlowToView{
UIView *view = [[UIView alloc] initWithFrame:CGRectMake((self.frame.size.width-7.f)/2.f, (self.frame.size.height-7.f)/2.f, 7.f, 7.f)];
view.backgroundColor = [UIColor whiteColor];
[self addSubview:view];
[UIView animateWithDuration:1.5 delay:0.0 options:UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat animations:^{
view.alpha = 0.8;
view.layer.cornerRadius = 2.2;
view.transform = CGAffineTransformMakeScale(1.8,1.8);
} completion:^(BOOL finished){
}];
}

How can I fade a UIView in while moving it up?

I have a UIView and I want to give it an effect that causes it to start with an alpha of 0 and then while moving up 50 pixels animated it also changes to an alpha of 1. How can this be done in Objective-C?
[UIView animateWithDuration:1.0 animations:^{
//here change position and alpha
CGRect newFrame = view.frame;
newFrame.origin.y += 50;
view.frame = newFrame;
view.alpha = 1.0;
} completion:^(BOOL finished) {
//called when animation did finish. do what you want
}];
https://developer.apple.com/library/ios/documentation/windowsviews/conceptual/viewpg_iphoneos/animatingviews/animatingviews.html
Everything about animations.
It's all right there.
//something similar to what you want:
- (IBAction)showHideView:(id)sender
{
// Fade out the view right away
[UIView animateWithDuration:1.0
delay: 0.0
options: UIViewAnimationOptionCurveEaseIn
animations:^{
thirdView.alpha = 0.0;
}
completion:^(BOOL finished){
// Wait one second and then fade in the view
[UIView animateWithDuration:1.0
delay: 1.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
thirdView.alpha = 1.0;
}
completion:nil];
}];
}
Something like this would do the trick:
UIView *box = [[UIView alloc] initWithFrame:CGRectMake(self.view.center.x, self.view.center.y, 100, 50)];
box.backgroundColor = [UIColor blackColor];
box.alpha = 0.0f;
[self.view addSubview:box];
[UIView animateWithDuration:2.0f
animations:^{
box.alpha = 1.0f;
CGRect frame = CGRectMake(self.view.center.x, self.view.center.y - 100, 100, 50);
[box setFrame:frame];
}];

List of Buttons lighting up at random

The method im trying to achieve is set a button to 0.5 alpha then back to 1 in the space of three seconds. After its executed 5 time on the four buttons the block of code is finished. Im struggling to find a way in which this can be achieved becasue right now the block below will be an infinite loop when i want it to be only executed through once.
int rand=random()%5;
switch (rand) {
case 1:{
[UIView beginAnimations:NULL context:NULL];
[UIView setAnimationDuration:5.0];
[btnYellow setAlpha:0.5];
[btnYellow setAlpha:1];
[UIView commitAnimations];
}
break;
case 2:
[UIView beginAnimations:NULL context:NULL];
[UIView setAnimationDuration:5.0];
[btnRed setAlpha:0.5];
[btnRed setAlpha:1];
[UIView commitAnimations];
break;
case 3:
[UIView beginAnimations:NULL context:NULL];
[UIView setAnimationDuration:5.0];
[btnBlue setAlpha:1];
[UIView commitAnimations];
case 4:
[UIView beginAnimations:NULL context:NULL];
[UIView setAnimationDuration:5.0];
[btnGreen setAlpha:1];
[UIView commitAnimations];
break;
case 5:
[UIView beginAnimations:NULL context:NULL];
[UIView setAnimationDuration:5.0];
[btnYellow setAlpha:1];
[UIView commitAnimations];
break;
}
As you are setting up the button's alpha to 0.5 and then to 1 immediately, the button's alpha won't animate. You can get an idea this snippet
[UIView animateWithDuration:0.3 animations:^{
[your_btn setAlpha:0.5];
} completion:^(BOOL finished) {
if(finished)
[self performSelector:#selector(revertAlphaToOne) withObject:nil afterDelay:0.5];
}];
And in that revertAlphaToOne Method, you can revert the button's alpha to 1 as
[UIView animateWithDuration:0.3 animations:^{
[your_btn setAlpha:1.0];
} completion:nil
}];
Adjust the time variables according to your likings And/Or call the second snippet in the first block's completion block itself.
Well, I've been using this site for several years, and I was due for a nice thorough answer to give back.
I built a project and accomplished the functionality you desired. Some notes:
-The key is recursion! You need to animate the fade out (using the function I provided) and, upon completion, animating the fade back in using the same function. Once completed, exercise recursion and prepare to call itself (beginAnimations) until all ints=5.
-I decided to fade from 1->.5->1 because the .5 alpha was annoying me. Shouldn't be hard to switch that around if you want it reversed.
-To make sure no button fades more than fives times, you need to declare and increment an int corresponding to each button.
-Use arc4random(), not random(). Random is for debugging as you will have the same result every time.
-Keep your switch case's straight; was hard to understand what you wanted to be different between them. On this note, use breaks and a default statement! Good luck employing all this into your app.
.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self.view setBackgroundColor:[UIColor blackColor]];
//declare and define button specifics
btnYellow = [UIButton buttonWithType: UIButtonTypeCustom];
[btnYellow setBackgroundColor: [UIColor yellowColor]];
btnYellow = [self buttonTraits:btnYellow];
[btnYellow setFrame: CGRectMake(20, 20, 280, 30)];
[btnYellow setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[btnYellow.titleLabel setFont:[UIFont boldSystemFontOfSize:14]];
btnRed = [UIButton buttonWithType: UIButtonTypeCustom];
[btnRed setBackgroundColor: [UIColor redColor]];
[btnRed setFrame: CGRectMake(20, 60, 280, 30)];
[btnRed setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[btnRed.titleLabel setFont:[UIFont boldSystemFontOfSize:14]];
btnBlue = [UIButton buttonWithType: UIButtonTypeCustom];
[btnBlue setFrame: CGRectMake(20, 100, 280, 30)];
[btnBlue setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[btnBlue.titleLabel setFont:[UIFont boldSystemFontOfSize:14]];
[btnBlue setBackgroundColor: [UIColor blueColor]];
btnGreen = [UIButton buttonWithType: UIButtonTypeCustom];
[btnGreen setFrame: CGRectMake(20, 140, 280, 30)];
[btnGreen setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[btnGreen.titleLabel setFont:[UIFont boldSystemFontOfSize:14]];
[btnGreen setBackgroundColor: [UIColor greenColor]];
//add buttons to the view
[self.view addSubview:btnYellow];
[self.view addSubview:btnRed];
[self.view addSubview:btnBlue];
[self.view addSubview:btnGreen];
//set the counting ints to 0
yellowCount = 0, redCount = 0, blueCount = 0, greenCount = 0;
//run through the animations the first time
[self beginAnimations];
}
-(void)beginAnimations
{
if (!(yellowCount==5 && redCount==5 && blueCount == 5 && greenCount == 5))
{
//if you want 5 buttons, define another one, then the next line would be int rand=random()%6;
int rand=((arc4random()%5)+1); //arc4random gives 0-3; add 1 for 1-4
switch (rand) {
case 1:
{
//make sure this button hasn't gone through the process 5 times already
if (yellowCount<5)
{
//increment the button's count
yellowCount++;
//set up animation with 1.5 second duration (alpha decline from 1->.5)
[UIView animateWithDuration:1.5 delay:0 options: UIViewAnimationOptionCurveEaseOut animations:^{
[btnYellow setAlpha:.5];
} completion:^(BOOL finished)
{
if(finished==TRUE)
{
[UIView animateWithDuration:1.5 delay:0 options: UIViewAnimationOptionCurveEaseOut animations:^{
[btnYellow setAlpha:1];
} completion:^(BOOL finished) {
if(finished==TRUE)
{
[self beginAnimations];
}
}];
}
}];
}
else
{
//restart the animation hoping to get another button that hasn't gone 5 times yet
[self beginAnimations];
}
}
break; //you forgot a break here. can cause troubles
case 2:
{
if (redCount<5)
{
redCount++;
[UIView animateWithDuration:1.5 delay:0 options: UIViewAnimationOptionCurveEaseOut animations:^
{
[btnRed setAlpha:.5];
} completion:^(BOOL finished)
{
if(finished==TRUE)
{
[UIView animateWithDuration:1.5 delay:0 options: UIViewAnimationOptionCurveEaseOut animations:^{
[btnRed setAlpha:1];
} completion:^(BOOL finished) {
if(finished==TRUE)
{
[self beginAnimations];
}
}];
}
}];
}
else
{
[self beginAnimations];
}
}
break;
case 3:
{
if (blueCount<5)
{
blueCount++;
[UIView animateWithDuration:1.5 delay:0 options: UIViewAnimationOptionCurveEaseOut animations:^
{
[btnBlue setAlpha:.5];
} completion:^(BOOL finished)
{
if(finished==TRUE)
{
[UIView animateWithDuration:1.5 delay:0 options: UIViewAnimationOptionCurveEaseOut animations:^{
[btnBlue setAlpha:1];
} completion:^(BOOL finished) {
if(finished==TRUE)
{
[self beginAnimations];
}
}];
}
}];
}
else
{
[self beginAnimations];
}
}
break; //you forgot another break here. can cause troubles
case 4:
{
if (greenCount<5)
{
greenCount++;
[UIView animateWithDuration:1.5 delay:0 options: UIViewAnimationOptionCurveEaseOut animations:^
{
[btnGreen setAlpha:.5];
} completion:^(BOOL finished)
{
if(finished==TRUE)
{
[UIView animateWithDuration:1.5 delay:0 options: UIViewAnimationOptionCurveEaseOut animations:^{
[btnGreen setAlpha:1];
} completion:^(BOOL finished) {
if(finished==TRUE)
{
[self beginAnimations];
}
}];
}
}];
}
else
{
[self beginAnimations];
}
}
break;
default:
{
//in case of an awry number, restart the process (be wary; infinite loop potential)
[self beginAnimations];
}
break; //it is of good practice to always have a default method in switch statements
}
}
else
{
//the process is complete
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
{
UIButton *btnYellow;
UIButton *btnRed;
UIButton *btnBlue;
UIButton *btnGreen;
int yellowCount;
int redCount;
int blueCount;
int greenCount;
}
#end
The problem is that in cases 1 and 2, you set the alpha value to 0.5 and then IMMEDIATELY back to 1. So when the animation starts, it is simply 1 and will remain so. Just delete the 2nd assignment, and the animation will change alpha to 0.5. PS: As already mentioned, the random number generated is from 0 to 4, and not from 1 to 5.

Setting UIView Frame

I'm trying to resize my UITextView when the keyboard appears, but I don't know what I'm doing wrong.
I have these three lines of code called when the keyboard appears:
CGSize kbSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
textView.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height-kbSize.height);
NSLog(#"%f,%f,%f,%f", textView.frame.origin.x, textView.frame.origin.y, textView.frame.size.width, textView.frame.size.height);
For some really odd reason my keyboard doesn't appear and here is what is logged:
0.000000,-180.000000,480.000000,180.000000
Why is the CGRects y origin getting set to -180 when it is hardcoded in at 0?
EDIT: textView is a UITextView I created programatically. I didn't use Interface Builder.
EDIT2: It seems that the problem is that the view is autoresizing when rotated.
You can try this :
- (void) moveTextViewForKeyboard:(NSNotification*)aNotification up:(BOOL)up {
NSDictionary* userInfo = [aNotification userInfo];
NSTimeInterval animationDuration;
UIViewAnimationCurve animationCurve;
CGRect keyboardEndFrame;
[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
[[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardEndFrame];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:animationDuration];
[UIView setAnimationCurve:animationCurve];
CGRect newFrame = textView.frame;
CGRect keyboardFrame = [self.view convertRect:keyboardEndFrame toView:nil];
keyboardFrame.size.height -= tabBarController.tabBar.frame.size.height;
newFrame.size.height -= keyboardFrame.size.height * (up?1:-1);
textView.frame = newFrame;
[UIView commitAnimations];
}
Hope it'll help

iPhone SDK: TextView, Keyboard in Landscape mode

How do I make sure that the textview is shown and the keyboard is not obscuring the textview, while in landscape.
Using UICatalog I created a TextViewController which works. In it there are two methods for calling the keyboard and making sure that textView is positioned above the keyboard. his just works great in Portrait mode.
I got the Landscape mode working, but on the textView is still being put to the top of the iPhone to compensate for the keyboard in portrait mode.
I changed the methods for showing the keyboards.
Below is the code for this methods: (I will just let see the code for show, since the hide code will be the reverse..
- (void)keyboardWillShow:(NSNotification *)aNotification
{
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if (orientation == UIInterfaceOrientationPortrait) {
// the keyboard is showing so resize the table's height
CGRect keyboardRect = [[[aNotification userInfo] objectForKey:UIKeyboardBoundsUserInfoKey] CGRectValue];
NSTimeInterval animationDuration = [[[aNotification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect frame = self.view.frame;
frame.size.height -= keyboardRect.size.height;
[UIView beginAnimations:#"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
} else if (orientation == UIInterfaceOrientationLandscapeLeft) {
NSLog(#"Left"); // Verijderen later
CGRect keyboardRect = [[[aNotification userInfo] objectForKey:UIKeyboardBoundsUserInfoKey] CGRectValue];
NSTimeInterval animationDuration = [[[aNotification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect frame = self.view.frame;
frame.size.width -= keyboardRect.size.height;
[UIView beginAnimations:#"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
} else if (orientation == UIInterfaceOrientationLandscapeRight){
NSLog(#"Right"); // verwijderen later.
CGRect keyboardRect = [[[aNotification userInfo] objectForKey:UIKeyboardBoundsUserInfoKey] CGRectValue];
NSTimeInterval animationDuration = [[[aNotification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect frame = self.view.frame;
frame.size.width -= keyboardRect.size.width;
[UIView beginAnimations:#"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
}
}
I know that I have to change the line frame.size.height -= keyboardRect.size.height but I do not seem to get it working.
I tried frame.size.width -= keyboardRect.size.height that did not work. Losing the keyboardRect and frame all together work, however off course the keyboard obscures the textview........
I found the above code wouldn't work when in Landscape Mode on iPad
Note: I am moving all Fields, as in my case that's what i needed :-)
- (void)keyboardWillShow:(NSNotification*)aNotification {
// Only do for Landscape Mode
if (UIInterfaceOrientationIsLandscape([self interfaceOrientation])){
NSDictionary *info = [aNotification userInfo];
NSValue *aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
CGSize keyboardSize = [aValue CGRectValue].size;
NSTimeInterval animationDuration = 0.300000011920929;
CGRect frame = self.view.frame;
frame.origin.x -= keyboardSize.height-44;
frame.origin.y -= keyboardSize.height-44;
frame.size.height += keyboardSize.height-44;
[UIView beginAnimations:#"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
viewMoved = YES;
}
keyboardInUse = YES;
}
- (void)keyboardWillHide:(NSNotification*)aNotification {
if (UIInterfaceOrientationIsLandscape([self interfaceOrientation])){
if (viewMoved) {
NSDictionary *info = [aNotification userInfo];
NSValue *aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
CGSize keyboardSize = [aValue CGRectValue].size;
NSTimeInterval animationDuration = 0.300000011920929;
CGRect frame = self.view.frame;
frame.origin.y += keyboardSize.height-44;
frame.origin.x += keyboardSize.height-44;
frame.size.height -= keyboardSize.height-44;
[UIView beginAnimations:#"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
viewMoved = NO;
}
}
keyboardInUse = NO;
}
If you think you need different code for the different orientations, you're doing something else wrong. Once the orientation has changed and your superview has responded, the value that needs changing should always be the frame's height.
Here is a code that I use for this purpose. It works on both iPad and iPhone is landscape and portrait modes (inspired by a code from Apple documentation):
// Call this method somewhere in your view controller setup code.
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
}
// Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWasShown:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
float offset;
if UIInterfaceOrientationIsPortrait(self.interfaceOrientation)
offset = kbSize.height;
else
offset = kbSize.width;
[UIView animateWithDuration:0.5
animations:^{
CGRect frameTxtField = myTextField.frame;
frameTxtField.origin.y -= offset;
myTextField.frame = frameTxtField;
}
];
}
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
float offset;
if UIInterfaceOrientationIsPortrait(self.interfaceOrientation)
offset = kbSize.height;
else
offset = kbSize.width;
[UIView animateWithDuration:0.5
animations:^{
CGRect frameTxtField = myTextField.frame;
frameTxtField.origin.y += offset;
myTextField.frame = frameTxtField;
}
];
}
Don't forget to call the registerForKeyboardNotifications method (e.g., in viewDidLoad).