I need to change size and position of a subview (call it playerView) of a view of a view controller. I have created properties for constraints I need to change. But when I animate the changes, only playerView is animated, but all of it's subviews are not: their size is changed instantly.
Here's the text:
self.playerViewTop.constant = screenHeight - MinizedPlayerTopOffset;
self.playerViewLeading.constant = MinimizedPlayerOffset;
self.playerViewWidth.constant = MinimizedPlayerWidth;
self.playerViewHeight.constant = MinimizedPlayerHeight;
[UIView animateWithDuration: 2.0 animations: ^
{
[self.view layoutSubviews];
}];
I do not understand why that happens since I use autoLayout. Please help.
You need to call layoutIfNeeded() in the animations block, not layoutSubviews().
(You should actually never call layoutSubviews() yourself. It's a method called by the system during a layout pass and only intended for that purpose.)
[self.view layoutIfNeeded];
[self.subView setNeedsUpdateConstraints];
[self.subView updateConstraintsIfNeeded];
[UIView animateWithDuration:1.0f delay:0.0f
options:UIViewAnimationOptionLayoutSubviews animations:^{
[self.view layoutIfNeeded];
} completion:nil];
Related
I want to animate the center of a UIView, and I did this in viewDidLoad:
_test.center = CGPointMake(100.0,100.0);
[UIView animateWithDuration:10.0
delay:5
options:UIViewAnimationOptionCurveLinear
animations:^{_test.center = CGPointMake(100.0,-100.0);}
completion:^(BOOL finished) {
}];
But when I run the code, the center of test view is already at 100,-100. Why it doesn't animate?
Move the code from your viewDidLoad to your viewDidAppear. In viewDidLoad, the UIView has been loaded, but it is not visually present yet.
I guess you are using auto constraints which prevent animating views the way you are doing.
In order to fix this issue try these steps:
First:
Move your code to - (void)viewDidLayoutSubviews.
Second:
Do these steps before and after doing any animation to your view:
- (void)viewDidLayoutSubviews{
_test.translatesAutoresizingMaskIntoConstraints = YES;
_test.center = CGPointMake(100.0,100.0);
[UIView animateWithDuration:10.0
delay:5
options:UIViewAnimationOptionCurveLinear
animations:^{_test.center = CGPointMake(100.0,-100.0);}
completion:^(BOOL finished) {
}];
[_test updateConstraints];
}
I have a UIScrollView placed inside of a ViewController to which I have given AutoLayout Constraints and all of them are satisfied.
The scrollView contains around 20 UIButton subviews. I have given autolayout constraints to them also and they all are also satisfied.
What I need to do is I want to animate those buttons when the view is first launched. This is my code for animation
for (UIButton *button in [scrollView subviews]) {
CGRect mainFrame = [button frame];
[UIView animateWithDuration:0.0 animations:^{
button.frame = CGRectMake(button.center.x, button.center.y, 0, 0);
} completion:^(BOOL finished) {
[UIView animateWithDuration:1 delay:0.5 usingSpringWithDamping:0.3 initialSpringVelocity:0.2 options:UIViewAnimationOptionCurveEaseOut animations:^{
button.frame = mainFrame;
} completion:^(BOOL finished) {
}];
}];
}
The subviews are not animating when I use this code.
But when I set the
[button setTranslatesAutoresizingMaskIntoConstraints:YES];
it works. But this time I get the error Unable to Simultaneously Satisfy constraints.
Is there any other method to do it or should I just ignore the error message and just go with it?
Don't modify the frames when using Auto Layout.
You should modify the constraints to achieve the animation and call [yourView layoutIfNeeded] in the animation block.
It works by setting setTranslatesAutoresizingMaskIntoConstraints because then setting the frame causes constraints to be created. These finally conflict with your already existing constraints and cause the constraint warning.
Alternatively you can use the view's transform property and animate that one to achieve your desired effect, since I think you only want something like a presentation animation. Then you don't have to modify the constraints.
You would do something like:
[UIView animateWithDuration:1.0 animations:^{
button.transform = CGAffineTransformMakeTranslation(10.0, 10.0);
}];
You should animate the values for the constants in the constraints instead of the frame for each button. Create internal properties for each constraint you would like to animate and then use UIView's animateWithDuration. For example:
self.myConstraint.constant = 10;
[button setNeedsUpdateConstraints];
[UIView animateWithDuration:1 animations:^{
[button layoutIfNeeded];
}];
i am trying to change tableview frame by using autolayout in animationWithDuration block. Like That;
[UIView animateWithDuration:0.3f animations:^{
weekdayOffersVerticalConstraint.constant = 80;
[headerView layoutIfNeeded];
[weekdayTableView layoutIfNeeded];
self.isTableViewSmall = YES;
} completion:^(BOOL finished) {
}];
my tableview's frames are changing with this code block, but when i scroll to down, cells coming from left side to right side, i thought it is about with [weekdayTableView layoutIfNeeded]; layoutIfNeeded effect to all subviews. How can i obstruct to effect to my tableview's cells?
Sorry for my bad english, Thank you very much for your answers and advices.
Call layoutIfNeeded before you begin the animation to update the constraints:
[headerView layoutIfNeeded];
[weekdayTableView layoutIfNeeded];
[UIView animateWithDuration:0.3f animations:^{
weekdayOffersVerticalConstraint.constant = 80;
[headerView layoutIfNeeded];
[weekdayTableView layoutIfNeeded];
self.isTableViewSmall = YES;
} completion:^(BOOL finished) {
//
}];
You probably also don't want to set that BOOL property inside the animation block unless you have a method that overrides it intentionally during the animation.
So i have a really weird problem at my hands and hours of search has provided nothing.
I have a uiview containing a uitextfield. Now initially this view is outside of the visible screen with coordinates like x=-500,y=-500.
However in response to a button press this view animates and moves into the center of the screen.
Now whenever i tap on a uitextfield that is the subview of this view.This view moves back to its original coordinates outside the screen.
I have frantically checked my code and there is nothing that is moving the view outside again once its in. Any help in explaining this very unfamiliar behaviour would be really appreciated.
This code moves the view onto the screen
- (IBAction)Register:(id)sender {
//(self.view.frame.size.width/2)-(self.SignUp_Screen.frame.size.width/2);
//self.login_Screen.hidden = YES;
self.blurView.hidden = NO;
//self.SignUp_Screen.layer.zPosition = 5;
NSLog(#"Register");
self.SignUp_Screen.hidden = NO;
[UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
self.SignUp_Screen.frame = CGRectMake(35, 50,self.SignUp_Screen.frame.size.width , self.SignUp_Screen.frame.size.height);
} completion:^(BOOL finished) {
}];
}
and these are the delegate methods for the textfield
-(void)textFieldDidEndEditing:(UITextField *)textField
{
NSLog(#"TextFieldEndEditing");
[textField resignFirstResponder];
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
NSLog(#"textFieldShouldReturn");
[textField resignFirstResponder];
return YES;
}
As Wezly hints at, if you are using autolayout, you don't modify the frame directly anymore. That's the old world. You want to have an Outlet / property for the constraint and animate it.
[UIView animateWithDuration:0.25
animations:^{
SignUp_Screen.centerXConstraint.constant = ...;
SignUp_Screen.centerYConstraint.constant = ...;
[SignUp_Screen layoutIfNeeded];
}];
See here and here for more details.
You should not modify frame if you are using auto layout. You should animate view by animating constraint's constant. For example:
NSLayoutConstraint *viewY; //constraint from superview top to view top
viewY.constant = 100;
[self.view setNeedsUpdateConstraints];
[UIView animateWithDuration:0.3f animations:^{
[self.view layoutIfNeeded];
}];
The way i solved this problem was by linking an IBOutlet to the constraint I wanted to change and then animating it's constant value.
.h
#interface ViewController : UIViewController {
IBOutlet NSLayoutConstraint *constraintHandle;
}
.m
[UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
constraintHandle.constant = self.view.center.x;
[SignUp_Screen layoutIfNeeded];
} completion:^(BOOL finished) {
}];
Don't forget to link the IBOutlet to your constraint in your storyboard or xib.
I use this code to move my view
[UIView animateWithDuration:0.3 animations:^{
[MyView setTransform:CGAffineTransformMakeTranslation(260, 0)];
} completion:^(BOOL finished) {
}];
MyView is a subview of self.view
I want to move it to right with 260
but it will first move to left with 130 and no animate
and then move to right with 260 and animate
I don't know why MyView move to left first?
The problem is that you are using auto layout. For a simple animation, trying turning off auto layout in storyboard.
Your animation should work then as expected.
I guess the problem is that the MakeTranslation function is making your view reset it's position before animating to the new transform.
Try this:
[UIView animateWithDuration:0.3 animations:^{
[MyView setTransform:CGAffineTransformTranslate(myView.transform, 260, 0)];
} completion:^(BOOL finished) {
}];