I'm trying to move a simple uiview 30 points up. However, no matter what I do I can't move it.
I'm developing in iOS 7.1
Now, I finally found out that I have auto layout on, however I don't have any constrains for this view. It was a simple drag from the object library and place in a view controller. I've tried various things to get it to move. I can animate properties, such as alpha and what have you but I can't for the life of me move it.
Below is what I've tried:
[UIView animateWithDuration:1.0f animations:^{
CGREct oldFrame = self.viewWantingToMove.frame;
self.viewWantingToMove.frame = CGRectMake(self.viewWantingToMove.frame.origin.x, self.viewWantingToMove.origin.y, self.viewWantingToMove.size.width, self.viewWantingToMove.width.height);
});
This doesn't work
[UIView animateWithDuration:1.0f animation:^{
self.viewWantingToMove.center = CGPoint(self.viewWantingToMove.frame.origin.x, self.viewWantingToMove.frame.origin.y-30
}];
Again nadda...
After I figured it might have something with auto layout, mind you I can't turn it off because I have to use it, I then tried this.
[self.viewWantingToMove layoutIfNeeded];
[UIView animateWithDuration:1.0f animation:^{
self.viewWantingToMove.center = CGPoint(self.viewWantingToMove.frame.origin.x, self.viewWantingToMove.frame.origin.y-30
[self.viewWantingToMove layoutIfNeeded];
}];
This gives me animation...... BUT backwards. it starts off 30 points up and then moves back to it's original position. Can anyone help me with this? Its getting to one of those moments where you feel like biting the monitor.
When you're using auto layout, you shouldn't be setting any frames. To move or resize views, you should modify the constraints instead. The fact that you didn't add any constraints does mean they're not there. The system adds default constraints for you. You should set the constraints you want, so you know what they are (try ones to the top of the view, to the left side, and ones for height and width). Make an IBOutlet to the constraint to the top of the view (lets call it topCon), then you can modify that one in code to animate it,
[UIView animateWithDuration:1.0f animation:^{
self.topCon.constant -= 30;
[self.view layoutIfNeeded];
}];
Related
I wonder if I programmatically can center a view from one element to another.
The screenshot under explains it.
If I click on "Sort2" I want to animate the view from Sort2 to be centered under Sort1 instead
In your selector for Sort2 button, add the line
[UIView animateWithDuration:1.0 animations:^{
sort2View.center = CGPointMake(sort1View.center.x, sort1View.center.y + 50)
}];
Another much cleaner approach would be to add UIConstraints.
There is a better way with using layout constraints. You should give center constraint between Sort2 and your view and set it's priority to High. After that give center constraint between Sort1 and your view and set it's priority to Low. After that you just need to change their priorities use this code. (In code, yourView is your whole view including these three views)
[UIView animateWithDuration:0.5 animations:^{
[yourView layoutIfNeeded];
}];
It's kind the weird I'm facing right now, I know that adding constraints in an AutoLayout IB is simple. But I really couldn't figure-out why my simple constraints are not working when I'm resizing (ZoomIn Animation) a UIView.
The View I'm targeting to zoomIn works fine, but the subviews within it is not being positioned well. It seems that the constraints are not working.
From this setup, where in the Yellow Boxes are UIViews and the Green Boxes are UIImageViews.
When I tapped on a Yellow Box, it should zoomIn, as what is shown on the photo below it.
These are the constraints:
This should be the expected resulting upon zoomIn AnimationBut I got no luck, The yellow box zoomIn but the Green Box is let on its old position and did not changed size.
I put a leading, trailing, topSpace, and bottomSpace from Yellow Box to Green Box already.
My code for resizing the yellow box is:
- (void) resizeViewWithZoomInAnimation: (UIView*)view duration:(float)secs option:(UIViewAnimationOptions) option {
//sets the new width and height of deal's view
float newWidth = view.superview.frame.size.width - 20;
float newHeight = view.superview.frame.size.height - 20;
[UIView animateWithDuration:secs delay:0.0 options:option
animations: ^{
switch ([view tag]) {
case 1:
[view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, newWidth, newHeight)];
break;
case 2:
[view setFrame:CGRectMake(CGRectGetMaxX(view.frame),CGRectGetMinY(view.frame), -newWidth , newHeight)];
break;
case 3:
[view setFrame:CGRectMake(CGRectGetMinX(view.frame),CGRectGetMaxY(view.frame), newWidth , -newHeight)];
break;
case 4:
[view setFrame:CGRectMake(CGRectGetMaxX(view.frame),CGRectGetMaxY(view.frame), -newWidth, -newHeight)];
break;
}
}
completion:nil];
}
This should be the expected resulting upon zoomIn Animation:
When trying to animate with Auto Layout, you should not change view's frames directly. Instead, you should animate changes in constraints.
To access constraints from storyboard you can simply create IBOutlets for them.
[containerView layoutIfNeeded]; // complete pending layout operations (optional)
[UIView animateWithDuration:1.0 animations:^{
// Update constraints
self.viewConstraint1.constant = NEW_VALUE;
self.viewConstraint2.constant = NEW_VALUE;
// Animate the changes
[containerView layoutIfNeeded];
}];
Note that you usually want to call layoutIfNeeded on the super view(or higher) of the view you are trying to animate.
I recommend reading more on Auto Layout in Apple's official guide.
A tweak to the above answer, I used from within a UIViewController
[self.view layoutIfNeeded];
[UIView animateWithDuration:.5
animations:^{
myConstraint.constant = 64;
[self.view layoutIfNeeded];
}
completion:^(BOOL finished) {
// whatever
}];
Changes of note: Apple docs recommend using layoutIfNeeded, and calling this both before and within the animation block. This is so that you can be sure the animation stack is cleared before beginning.
Also, you are to call layoutIfNeeded on the parent view of the constraint you will be animating, not on the view who owns the constraint. Thanks to #nkukushkin for the initial answer.
It's also important to have your constraints set up correctly. The 'fix constraints' tool in IB won't necessary set them up in a way that works correctly for animating. For me I had to go through them and think through how I wanted the dependencies to work, which is of course expected but might not be obvious to the beginner (and results in errors).
When you are using constrains, pre-constrains are generated. When you act on position and size, remove constrains while animating the view or do following:
yourView.translatesAutoresizingMaskIntoConstraints = YES;
I have searched far and wide for a solution to this but to no avail.
The problem I am having is when I animate a UITableView's height in my application, the scrollable area stays the same size. ie. If you tap and drag on the part of the tableview that has increased in height, nothing will happen - but if you tap and drag in the small original frame of the tableview it scrolls perfectly fine.
The code I use to animate the tableview is as follows:
[UIView animateWithDuration:0.3 animations:^{
self.view.frame = extendedFrame;
self.tbl_body.frame = extendedFrame;
}];
Thanks in advance!
Ok so I finally solved this but still do not quite understand the issue.
The only way I could fix it was to set the frame to the extended frame on initiliazation, then resize it back to the minimized frame. Only then when it is extended is the gesture recogniser the correct size.
I know not perfect but I had to go with this for lack of a better solution
This is a shot in the dark but... have you tried using completion block to reload the data?
[UIView animateWithDuration:0.3 animations:^{
self.tbl_body.frame = extendedFrame;
}completion:^(BOOL finished){
[self.tbl_body reloadData];
}];
I've never worked with autolayout constraints before. I have a small new app I'm working on and noticed that the NIB's views are defaulting to autolayout. So, I figured I'd take the opportunity to work with it and try to figure out where Apple is going with this.
First challenge:
I need to resize an MKMapView and I'd like to animate it to the new position. If I do this the way I'm used to:
[UIView animateWithDuration:1.2f
animations:^{
CGRect theFrame = worldView.frame;
CGRect newFrame = CGRectMake(theFrame.origin.x, theFrame.origin.y, theFrame.size.width, theFrame.size.height - 170);
worldView.frame = newFrame;
}];
...then the MKMapView will 'snap' back to its original height whenever a sibling view gets updated (in my case a UISegmentedControl's title is being updated [myUISegmentedControl setTitle:newTitle forSegmentAtIndex:0]).
So, what I think I want to do is change the constraints of the MKMapView from being equal to the parent view's hight to being relative to the top of the UISegmentedControl that it was covering: V:[MKMapView]-(16)-[UISegmentedControl]
What I want is for the MKMapView height to shorten so that some controls beneath the map view are revealed. To do so I think I need to change the constraint from a fixed full size view to one where the bottom is constrained to the top of a UISegmentedControl...and I'd like it to animate as view shrinks to new size.
How does one go about this?
Edit - this animation is not animating though the bottom of the view does move up 170 instantly:
[UIView animateWithDuration:1.2f
animations:^{
self.nibMapViewConstraint.constant = -170;
}];
and the nibMapViewConstraint is wired up in IB to the bottom Vertical Space constraint.
After updating your constraint:
[UIView animateWithDuration:0.5 animations:^{[self.view layoutIfNeeded];}];
Replace self.view with a reference to the containing view.
This works for me (Both iOS7 and iOS8+). Click on the auto layout constraint you would like to adjust (in interface builder e.g top constraint). Next make this an IBOutlet;
#property (strong, nonatomic) IBOutlet NSLayoutConstraint *topConstraint;
Animate upwards;
self.topConstraint.constant = -100;
[self.viewToAnimate setNeedsUpdateConstraints];
[UIView animateWithDuration:1.5 animations:^{
[self.viewToAnimate layoutIfNeeded];
}];
Animate back to original place
self.topConstraint.constant = 0;
[self.viewToAnimate setNeedsUpdateConstraints];
[UIView animateWithDuration:1.5 animations:^{
[self.viewToAnimate layoutIfNeeded];
}];
There is a very good tutorial from apple itself that explain how to use animation with autolayout.
Follow this link and then find the video named "Auto layout by example"
It gives some interesting stuff about autolayout and the last part is about how to use animation.
I have made this small demo available. It shows how auto-layout constraints can be changed and animated in a very simple example. Simply take a look at the DemoViewController.m.
Most people use autolayout to layout items on their views and modify the layout constrains to create animations.
An easy way to do this without a lot of code is creating the UIView you want to animate in Storyboard and then creating a hidden UIView where you want the UIView to end. You can use the preview in xcode to make sure both UIViews are where you want them to be. After that, hide the ending UIView and swap the layout constraints.
There is a podfile for swapping layout constrains called SBP if you don't want to write it yourself.
Here's a tutorial.
No need to use more IBOutlet reference of the constraint instead of this you can directly access or update already applied constraint either applied by Programmatically or from Interface Builder on any view using the KVConstraintExtensionsMaster library. This library is also managing the Cumulative behavior of NSLayoutConstraint.
To add Height Constraint on containerView
CGFloat height = 200;
[self.containerView applyHeightConstrain:height];
To update Height Constraint of containerView with animation
[self.containerView accessAppliedConstraintByAttribute:NSLayoutAttributeHeight completion:^(NSLayoutConstraint *expectedConstraint){
if (expectedConstraint) {
expectedConstraint.constant = 100;
/* for the animation */
[self.containerView updateModifyConstraintsWithAnimation:NULL];
}
}];
I want to make the width of an UIImageView larger through an animation. I have an UIView with and UIImageView made in the story board. What I want to achieve is so that it looks like the view is scaling from left to right, and keeping its original position. I have tried the following code, but what it does is animating the imageview from the top left corner of its parent view and moving and scaling it until it reaches the position and scale it had from the beginning.
[UIView animateWithDuration:4.0f delay:1.0f options:UIViewAnimationCurveEaseOut animations:^{
CGRect currentFrame = self.imageview1.frame;
currentFrame.size.width = 150;
self.imageview1.frame = currentFrame;
}completion:nil];
Any ideas why this behaviour?
A bit late answer, but I solved the problem. It seems that you cannot change the frame of views in code if autolayout is enabled. Instead you need to animate the constraints of the view, which you can set up in the storyboard and then animate like this:
[self.view layoutIfNeeded];
[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.bottomViewY.constant = -196;
[self.view layoutIfNeeded];
} completion:nil];
self.bottomViewY is a constraint which is assigned as an IBOulet. You need to call layoutIfNeeded as it will update the constraints.