UIToolbar doesn't show up after it's being hidden - objective-c

I got a UIButton which makes the UIToolbar show and hide.
- (IBAction)showHideToolbar:(id)sender{
if (toolBar.hidden == NO) {
[UIView animateWithDuration:0.25 delay:0.0 options:UIViewAnimationCurveLinear | UIViewAnimationOptionAllowUserInteraction animations:^(void){toolBar.alpha =0.0f;}completion:^(BOOL finished){
toolBar.hidden = YES;}];
NSLog(#"hides");
}
else
if (toolBar.hidden == YES) {
[UIView animateWithDuration:0.25 delay:0.0 options:UIViewAnimationCurveEaseIn | UIViewAnimationOptionAllowUserInteraction animations:^(void){toolBar.alpha =0.0f;}completion:^(BOOL finished){
toolBar.hidden = NO;
}];
NSLog(#"show");
}
}
The problem is that when i try to hide the toolBar,it works fine. But when i try to show it again, it won't show up.
Any ideas?

When you animate the showing of the toolbar you have to set the alpha to 1.0f in the animations block.
Below is the correct code; I've marked the line that I changed with a comment.
- (IBAction)showHideToolbar:(id)sender {
if (toolBar.hidden == NO) {
[UIView animateWithDuration:0.25f
delay:0.0f
options:UIViewAnimationCurveLinear | UIViewAnimationOptionAllowUserInteraction
animations:^(void){ toolBar.alpha = 0.0f; }
completion:^(BOOL finished){ toolBar.hidden = YES; }];
NSLog(#"hides");
}
else
if (toolBar.hidden == YES) {
[UIView animateWithDuration:0.25f
delay:0.0f
options:UIViewAnimationCurveEaseIn | UIViewAnimationOptionAllowUserInteraction
animations:^(void){ toolBar.alpha = 1.0f; } // Change from 0.0f to 1.0f
completion:^(BOOL finished){ toolBar.hidden = NO; }];
NSLog(#"show");
}
}

Related

iOS: How to drag a view along with finger till a particular y offset?

I am dragging a view from bottom to top with pre-defined offset positions using pan gesture.
My current implementation is such that the view updates after the gesture has ended. However, I want the view to update along with the finger (gesture is ongoing) and stop at the predefined (next) position when the gesture has ended.
Would appreciate if somebody could point me in the right direction. Thank you.
m_openPercentage = #"30,60";
- (void)onContentViewPanned:(UIPanGestureRecognizer *)gesture
{
CGPoint velocity = [gesture velocityInView:self.view];
NSArray *m_Openpercentage = [m_OpenPercentage componentsSeparatedByString:#","];
NSMutableArray *fullpercentage = [NSMutableArray arrayWithArray:m_Openpercentage];
float diffy = 0.0;
if(([gesture state] == UIGestureRecognizerStateEnded))
{
if(velocity.y < 0)
{
if(m_isfullscreen && ![fullpercentage containsObject:#"100"])
{
[fullpercentage addObject:#"100"];
}
diffy = 1-([[fullpercentage objectAtIndex:counter] floatValue]/100);
CGFloat ypos = self.view.frame.size.height * diffy;
[UIView animateWithDuration:1 delay:0 usingSpringWithDamping:0.5 initialSpringVelocity:0.5 options:0 animations:^{
[self.view setNeedsLayout];
self.view.frame = CGRectMake(0,ypos,self.view.frame.size.width,self.view.frame.size.height);
if(self.view.frame.origin.y==0)
[self showNavigationbar:1];
} completion:^(BOOL finished) {
}];
if(counter<[fullpercentage count]-1)
counter++;
}
else
{
if(counter>0)
{
float diffy = 1-([[fullpercentage objectAtIndex:counter-1] floatValue]/100);
CGFloat ypos = self.view.frame.size.height * diffy;
[UIView animateWithDuration:1 delay:0 usingSpringWithDamping:0.5 initialSpringVelocity:0.5 options:0 animations:^{
self.view.frame = CGRectMake(0,ypos,self.view.frame.size.width,self.view.frame.size.height);
} completion:^(BOOL finished) {
}];
}
else
{
diffy = 1-(m_initialPercentage/100);
CGFloat ypos = self.view.frame.size.height * diffy;
if(self.view.frame.origin.y < ypos)
{
[UIView animateWithDuration:1 delay:0 usingSpringWithDamping:0.5 initialSpringVelocity:0.5 options:0 animations:^{
self.view.frame = CGRectMake(0,ypos,self.view.frame.size.width,self.view.frame.size.height);
} completion:^(BOOL finished) {
}];
}
else
{
[self removeoverlayview];
[self.view removeFromSuperview];
id tmpControllerObj = [parentController getParentController];
[tmpControllerObj view].userInteractionEnabled = YES;
}
}
if((counter-1)>=0)
counter--;
[self showNavigationbar:0];
}
if(![m_Openpercentage containsObject:#"100"] && m_isfullscreen)
[self updatefullview];
}
}

Keep the End Position of Animation

I tried everything, but everytime its the same problem:
i want to move a button for y = 276. when the animation ends, my buttons jumps back to the startposition, but i want that the endanimationposition is the new position, and the button has to stay there, until a new animation is called.
tried with
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1];
CGPoint p = _cell00.center;
p.x += 100;
_cell00.center = p;
[UIView commitAnimations];
[UIView beginAnimations:nil context:nil];
same issue like
[UIView animateWithDuration:1.0 animations:^{
_cell00.frame = CGRectOffset(_cell00.frame, 0, 20);
}];
or
[UIView animateWithDuration:0.5 animations:^{
_cell00.center = CGPointMake(0, 20.0);
}];
EDIT:
I call this Animation with my Button called statisticsBUttonPressed.
- (IBAction)statisticsButtonPressed:(id)sender {
if (statOrGame == 0) {
statOrGame = 1;
}else {
statOrGame = 0;
}
NSLog(#"statOrGame? %d", statOrGame);
[self animateView:(UIButton *)sender];
}
-(void) animateView:(UIButton *)sender {
sender.userInteractionEnabled = NO;
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)
{ // The iOS device = iPhone or iPod Touch
NSLog(#"IS IPHONE 5");
CGSize iOSDeviceScreenSize = [[UIScreen mainScreen] bounds].size;
if (iOSDeviceScreenSize.height == 568)
{
if (statOrGame) {
[UIView animateWithDuration:1.0 animations:^{
_cell00.frame = CGRectOffset(_cell00.frame, 0, 20);
}];
}
}
}
}
The problem is that you're using auto layout. You can't (just) change the frame of a view that is positioned by auto layout, because what positions the view is its constraints. You need to change the constraints. You can do this at the end of the animation, or you can simply animate the change of constraints.

Animate a UITextField when changing from hidden to visible using AutoLayout

I have a UITextField that is set to hidden, when I click the search button I want to make it visible but I want to create an animation like a slide-in, is it possible to recreate this effect if i'm using autoLayout?
The code I used for the animation is the current (it creates a fade-in effect):
if(!currentSrcState)
{
_searchField.hidden = NO;
[UIView animateWithDuration:0.3
delay:0.0
options:UIViewAnimationOptionTransitionCurlDown
animations:^ {
_searchField.alpha = 1.0;
}
completion:nil];
currentSrcState = YES;
}
else
{
[UIView animateWithDuration:0.3
delay:0.0
options:UIViewAnimationOptionTransitionCurlDown
animations:^ {
_searchField.alpha = 0;
}
completion:^(BOOL finished){
_searchField.hidden = YES;
}];
currentSrcState = NO;
}
What I want to acheive is that when the _searchField is hidden the constraint gets recalculated in order to move what is under the searchField up
Instead of set the button to hidden, set its alpha value to 0.0 before load the view. Then change your code to:
if(!currentSrcState)
{
[UIView animateWithDuration:0.3
delay:0.0
options:UIViewAnimationOptionTransitionCurlDown
animations:^ {
_searchField.alpha = 1.0;
}
completion:nil];
currentSrcState = YES;
}
else
{
[UIView animateWithDuration:0.3
delay:0.0
options:UIViewAnimationOptionTransitionCurlDown
animations:^ {
_searchField.alpha = 0.0;
}
completion:nil];
currentSrcState = NO;
}

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.

How to move view for keyboard in portrait orientations

I have an app that runs in portrait and portraitUpsideDown only. I need to push the view up when the keyboard appears and pull it back down when it disappears. The following code works perfectly if the device stays in portrait, but if it is in portraitUpsideDown the view moves the wrong direction (-260 instead of 260), plus if the orientation changes while the keyboard is showing, it's not handled... The keyboardWillHide method works fine in both orientations. Is there a way to move the view RELATIVE to the keyboard or status bar so it doesn't matter what orientation the device is in???
- (void) keyboardWillShow:(NSNotification *) notification
{
NSLog(#"Keyboard Will Show");
double animationDuration;
animationDuration = [[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
[UIView animateWithDuration:animationDuration delay:0 options:UIViewAnimationCurveEaseIn animations:^{
self.view.center = CGPointMake(self.view.center.x, self.view.center.y + -260);
}completion:^(BOOL finished){
}];
}
- (void) keyboardWillHide:(NSNotification *) notification
{
double animationDuration;
animationDuration = [[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
NSLog(#"Keyboard Will Hide");
[UIView animateWithDuration:animationDuration delay:0 options:UIViewAnimationCurveEaseIn animations:^{
[self.view setFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
}completion:^(BOOL finished){
}];
}
I solved it (less than elegantly) this way:
NOTE: Things you SHOULD do, and I will change this code to do them eventually are: create a property to hold the keyboard animation duration so I can use it outside of the keyboard delegate methods, and similarly create a property for the offset and determine it using the userInfo for the height of the keyboard.
- (void) keyboardWillShow:(NSNotification *) notification
{
NSLog(#"Keyboard Will Show");
if (self.interfaceOrientation == UIInterfaceOrientationPortrait)
offset = -260;
else
offset = 260;
double animationDuration;
animationDuration = [[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
[UIView animateWithDuration:animationDuration delay:0 options:UIViewAnimationCurveEaseIn animations:^{
self.view.center = CGPointMake(self.view.center.x, self.view.center.y + offset);
}completion:^(BOOL finished){
}];
}
- (void) keyboardWillHide:(NSNotification *) notification
{
double animationDuration;
animationDuration = [[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
NSLog(#"Keyboard Will Hide");
[UIView animateWithDuration:animationDuration delay:0 options:UIViewAnimationCurveEaseIn animations:^{
self.view.center = CGPointMake(self.view.center.x, self.view.center.y - offset);
}completion:^(BOOL finished){
}];
}
- (void) keyboardDidShow
{
NSLog(#"Keyboard Did Show");
keyboardIsShowing = YES;
}
- (void) keyboardDidHide
{
NSLog(#"Keyboard Did Hide");
keyboardIsShowing = NO;
}
-(void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
if (keyboardIsShowing && UIInterfaceOrientationIsPortrait(toInterfaceOrientation))
{
if (toInterfaceOrientation == UIInterfaceOrientationPortrait && offset == 260)
offset = -260;
else if (toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown && offset == -260)
offset = 260;
else
return;
[UIView animateWithDuration:.25 delay:0 options:UIViewAnimationCurveEaseIn animations:^{
self.view.center = CGPointMake(self.view.center.x, self.view.center.y + 2* offset);
}completion:^(BOOL finished){
}];
}
}
Unfortunately you will have to manage this yourself. You can interrogate the current orientation and set your y-axis adjustment appropriately.
int movementDistance = -260;
if (UIInterfaceOrientationPortraitUpsideDown == [self interfaceOrientation]) movementDistance = -movementDistance;
You need to set the frame height, or set the contentInset for the view, not the center.