Object returns to the original position (after an animation) when keyboard appears - ios

I have this strange new issue: this code (that works perfectly)
[UIView animateWithDuration:0.4 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
CGRect frame = _logoClaim.frame;
frame.origin.y -= 180;
_logoClaim.frame = frame;
} completion:NULL];
moves a view that contains a UIImageView and an UILabel to the top of my self.view.
The view that moves unhides a UITextField.
When I try to write text into the UITextField, obviously appear the keyboard.
And at this moment, the view animated before, returns to the original start position!!!
What is the reason?

Put a completion block in your animation and check the finished value. The keyboard is cancelling the animation and the finished bool will be NO. I would disable input in the UITextField until the animation is completed. Do this in your completion block.
EDIT
Looking at your duration and re-reading the question,I may be mistaken with what I think you mean. If this answer is incorrect I will remove it.
Also, search your code for _logoClaim.frame in case you are adjusting it onKeyboardWillAppear

You would need to create outlet for its bottom/top space constraints and update the constant value of it inside the animation block.
[UIView animateWithDuration:0.4
...
animations:^{
/*Update the value of the constraint outlet supposing it to be a bottom space constraint*/
_layoutConstraintBottom += 180;
[self.logoClaim layoutIfNeeded];
} completion:NULL];
Do not forget to call -layoutIfNeeded for your animating view.

Related

prevent to view appear with animmation

I have a problem that my custom navigation bar appears for the first time with animation. I think it happens because I use auto-layout and it animates it self into the state of landscape or portrait. But I want to have a functionality, that after first time I enter the screen everything is still, and where it belongs. and after that if I turn the screen or if I do something all the animations appears like now.
Is there a good think to omit the first animations when the view creates itself?
The animations are : labels floating from left to right. and 1 label appears as from 0px width and height it scales into 100% width and height
code:
[self.navigationController.navigationBar addSubview:self.topBar];
self.topbar is UIView. I have added it to block [UIView performWithoutAnimation:^{ }]; but it does not helps, everytime the view appears for the first time I have my labels floating from left to right.
The answer is that I used some methods [self layoutIfNeeded]; After setting the constraint. The solution is to have a method set like this:
- (void) yourAnimation:(BOOL)animated{
if(animated){
[UIView animateWithDuration:0.3 animations:^{
//your animated code
//[self layoutIfNeeded];
}];
}else{
[UIView performWithoutAnimation:^{
//your stuff without animation
}];
}
}

iOS - Cancel constraints animation

I'm animating constraints the usual way:
centerXsettingsBtnConstraint.constant = aValue;
[UIView animateWithDuration:.5
animations:^{
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
isAnimating = NO;}];
When I'm rotating the device I want to cancel this animation and update constraint with new values.
I tried to call
[self.view.layer removeAllAnimations];
but the animation still goes on till the rotation of the device is over. Only then I can update with new constraints, but during the rotation it's all a mess on the screen.
Is there a way to cancel constraints animation?
You must call the remove.. method on each subview:
[self.view.layer removeAllAnimations];
I'll use Swift:
for eachView in self.view.subviews {
eachView.layer.removeAllAnimations()
}
You need to remove animation on the specified view whose constraint or property is being changed in that particular animation.
Call removeAllAnimations() on the view on whom centerXsettingsBtnConstraint is applied.
You do not need to call removeAllAnimations() on each subview.
If you are not able to find the particular view, try to print someView.layer.animationKeys(), you will find the view on which animation is applied.
For Swift:
This will work to stop the animation of the constraint
yourComponent.layer.removeAnimation(forKey: "position")

UIView animation returns to origin

I have a UILabel inside of a UITableViewCell. I am trying to animate the label moving to the right when the user taps the cell. I have this code:
CGRect otherFrame = cellLabel.frame;
otherFrame.origin.x +=50;
[UIView animateWithDuration:1.0f animations:^{
cellLabel.frame = otherFrame;
}];
The odd thing that's happening is that the label is jumping 50 pixels to the left and animating back to its origin (where it was before the action began).
I actually had this working earlier in the week and didn't have any trouble with it, and after scouring through the revision history, I can't figure out where I've gone wrong. I must be missing something stupid.
EDIT:
Based on the answer from Jakub, I found that this works:
[UIView animateWithDuration:0.01f animations:^{}
completion:^(BOOL finished)
{
CGRect otherFrame = cellLabel.frame;
otherFrame.origin.x += 50;
[UIView animateWithDuration:1.0f animations:^{
cellLabel.frame = otherFrame;
}];
}];
Oddly, if I move all of the logic into a completion handler that performs a new animation after the first one completes (without the first actually doing anything), everything animates properly. This is super hacky, and I'm not at all happy with it.
Can anyone think of what would cause the initial animation to move the frame to the negative offset of the intended destination, only to animate it back to its origin, and why triggering a new animation as the completion handler of an empty animation would work?
EDIT 2:
I am going to mark Duncan's answer as the right one because it pointed me in the right direction, but I am still baffled why/how these symptoms can happen:
The animation moves the frame to the negative offset of the
destination, then animates it back to the origin (rather than from
the origin to the destination)
Running an empty animation block but adding another animation to the first block's completion handler animates correctly
Info for the attempted answers:
I have to use auto layout for the project, and as far as I know, I
can't disable it for a single view
I am not putting anything onto a background thread. I didn't try specifically dispatching to the main thread, but I think I was already there. Isn't all visible UI always on the main thread? It was animating, just not as expected.
The reason I didn't go the route of changing constraints to begin with is that I am using prototype cells and IB doesn't let you create IBOutlets from prototype cells. There's a bit of work to walk a constraint list and detect a specific one, so I left the constraints blank and tried to animate the frame (and as I said, it was working earlier in the week -- and still worked when animating from an animation block's completion handler).
So the final solution was to add constraints to the container cell (the important one here being the leading), then to animate, I had to find the constraint:
NSLayoutConstraint *titleLeadingConstraint = nil;
for( NSLayoutConstraint *constraint in cellLabel.superview.constraints )
{
if( constraint.firstItem == cellLabel && constraint.firstAttribute == NSLayoutAttributeLeading )
{
titleLeadingConstraint = constraint;
}
}
Then set the constraint constant:
titleLeadingConstraint.constant = 55.0;
Then set the animation block:
[UIView animateWithDuration:1.0f animations:^{
[self.view layoutIfNeeded];
}];
This solution should be more future proof (and robust, reliable and stable) than moving the frame, but it turned out to be a fair amount of work in discovery.
Do you have auto layout set in your storyboard or XIB by mistake? (It is on by default). If so you either need to turn AutoLayout off or animate a constraint rather than manipulating your view's frame.
Where are you calling this code?
Try calling UIView animateWithDuration:... method on the main thread, in a
dispatch_async(dispatch_get_main_queue(), ^{
// Your animation here
});
If this method is not executed on the main thread, it usually jumps to the final stage of the animation.
You should reset the origin after animation.

How to translate an entire UIView and retain gesture recognition?

I have a UIView "MainView" that initially appears as follows:
The gradient bar is part of MainView, the whitespace beneath is part of a Container View subview.
When the search button in top-right is tapped, I animate a searchBar from offscreen to be visible in the view:
I manage to do this by the following code:
CGRect currentViewFrame = self.view.bounds;
currentViewFrame.origin.y += searchViewHeight;
[UIView animateWithDuration:0.4
delay:0.0
usingSpringWithDamping:1.0
initialSpringVelocity:4.0
options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.view.frame = currentViewFrame;
}
completion:^(BOOL finished)
{
}];
Visually, the result of this animation is perfect. The entire view shifts, and the searchBar is now on screen. However, the searchBar does not respond to interaction. Correct me if I'm wrong, but I expect this is because the MainView's frame no longer includes the screen area that the searchBar now occupies, so its effectively a gesture deadzone.
So this makes me think that instead of lazily animating the entire MainView down to accomodate the searchBar, I must instead individually translate all subviews of MainView one at a time. In this simple situation, that would not be a big problem, but I can envision a circumstance with tens of subviews making that completely unrealistic.
What is the best method to accomplish what I am trying to do? Is there a secret to animating entire views/subviews without having gesture deadzones? Thanks in advance!!

hide/unhide UIPicker with the same animation

im currently making a project where i need to hide my UIPicker, i've done all the hiding and animation stuff with this code,
on button press event this code is written:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.8];
CGAffineTransform transfrom = CGAffineTransformMakeTranslation(0, -200);
self.picker.transform = transfrom;
self.picker.alpha = self.picker.alpha * (-1) + 1;
[UIView commitAnimations];
and on view did load initialized;
self.picker.alpha = 0;
[self.view addSubview:self.picker]; //i dont really need this one
so here the picker will appear from button to top (0,-200) but when i click the button again it dissapears right away as self.picker.alpha goes to 0. i tried also putting animation delay and [UIView setAnimationDelay:3]; and tried also to set the animationDuration more but it does not effect when its going to hide.
i would like to know if how do i make the UIPicker hide in the same manner as it appears.
hope its not so confusing.
thanx
To reset the view to its original position you would want to reset the transform to CGAffineTransformIdentity.
As #Wain mentioned, you have changed the transform property while appearing the UIPickerView.
When you want to disappear the Picker View on click of a button you need to set its transform again.
Here is a link to learn animation in UIView in iOS:
http://developer.apple.com/library/ios/#documentation/windowsviews/conceptual/viewpg_iphoneos/animatingviews/animatingviews.html

Resources