I use a UICollectionView with UICollectionViewFlowLayout. I change the height of a UICollectionViewCell if a user touches it. To achieve that I use performBatchUpdates:to animate the height change. This works perfectly and the change gets animated with a standard grow and shrink animation.
But I would like to change this standard animation. How would I do that? I can't seem to find any hint on how to influence the animation type used.
Thanks to the hint here https://stackoverflow.com/a/15068865/956433 it is possible to wrap the performBatchUpdates: into a UIView animation block. So to change the standard grow and shrink animation to a more fancy spring animation you could implement the following:
[UIView animateWithDuration:0.5
delay:0.0
usingSpringWithDamping:0.5
initialSpringVelocity:0.0
options:0
animations:^{
[collectionView performBatchUpdates:^{
// your changes to the data
} completion:nil];
} completion:nil];
Related
I am trying to animate change UITableView height constraint using
+ transitionWithView:duration:options:animations:completion:. When the options is set, the UITableViewCell contentView's subview UIView also animates. The effect is like below. As you can see the cell underneath the window goes up and the red dot view's bounds animates to the predefined constraint. If I don't set the animation options, it won't be like this. But I need the animation when I change the UITableView height. So how to keep the table view height animation and disable the table view cell contentView's sub view animation? The code is below. The red dot view is a UIView with a red background color. Is there any way to disable UITableViewCell contentView's subview animation?
- (void)changeTableViewHeight {
self.tableViewTopVerticalSpaceConstraint.constant = 0;
[self.tableView setNeedsUpdateConstraints];
[self.view setNeedsUpdateConstraints];
[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
self.topViewHeightConstraint.constant = 50;
[self.topView setNeedsUpdateConstraints];
}];
}
//1. All constraints change must be done
self.hightConstraint.constant = 200;
self.anotherConstraint.constant = 34;
...
...
// 2. Indimate to iOS that this view need update constraints.
// Hey iOS I have modified few constraints. beware of it to layout that changes.
[self.view setNeedsUpdateConstraints];
// 3. I'm done, relayout the view with animation,
If I really changed any constraints to view.
[UIView animateWithDuration:1.5 animations:^{
[self.view layoutIfNeeded];
}];
Hope somebody will save their time
Had a similar problem that I solved with disabling animation for the layer of the view I didn't want animated. In your case ... implement the awakeFromNib method for your UITableViewCell subclass and disable the animations there. In your case something like ...
override func awakeFromNib() {
super.awakeFromNib()
redCircleView.layer.removeAllAnimations()
}
The thing is that UIView.animateWithDuration animates the views' layers and for new table view cells and other views created during or because of this animation, all changes will also be animated.
... EDIT ...
In the meantime I managed to find an even better solution. In the options parameter for the UIView.animateWithDuration use the UIViewAnimationOptionLayoutSubviews (or .LayoutSubviews in Swift) option. This layouts the subviews at animation commit time.
update code
- (void)changeTableViewHeight {
self.tableViewTopVerticalSpaceConstraint.constant = 0;
self.topViewHeightConstraint.constant = 50;
[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
[self.topView setNeedsUpdateConstraints];
}];
}
I'm using a custom UICollectionview Layout that displays the items in a circle. On a swipe up I reset the constraints on my collectionview and animate those constraint changes. I would like my items to animate with the constraint change so it's one smooth experience.
I get them to animate but only after the constraint change (I think), it looks messy and strange, check the screencast out here: http://cl.ly/ZmA0
This is the code in the swipe gesture method:
- (void)foo:(UISwipeGestureRecognizer *)gesture {
[self.view layoutIfNeeded];
[self.collectionView mas_remakeConstraints:^(MASConstraintMaker *make) {
make.width.equalTo(self.view.mas_width);
make.height.equalTo(self.collectionView.mas_width);
make.top.equalTo(self.view.mas_top).offset(50);
}];
[UIView animateWithDuration:1.0 animations:^{
[self.view layoutIfNeeded];
}];
[self.collectionView performBatchUpdates:^{
CircleLayout *layout = (CircleLayout *)self.collectionView.collectionViewLayout;
} completion:nil];
}
Any suggestions?
I'm not sure what MASConstraintMaker is (and the video is not working).
But within the performBatchUpdates block you are getting the collection view layout. What are you doing with it? it unused. Maybe that can point you to the right solution.
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];
}];
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 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.