I am trying to manually change rotation of a view in UIDynamics
, but the view's rotation is always reset after update. The documentation says, that UIDynamicAnimator
's updateItemUsingCurrentState:
method should update position and rotation of an item, but only position is updated.
I created a short example where a square view is falling from the screen and after a touch it should be positioned to the location of the touch and rotated to 45 degrees. However, no rotation happens (sometimes the rotation can be seen for a fraction of a second, but after that it is reset again):
#import "ViewController.h"
@interface ViewController ()
{
UIDynamicAnimator* _animator;
UIView* _square;
}
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
_square = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
_square.backgroundColor = [UIColor grayColor];
[self.view addSubview:_square];
_animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
UIGravityBehavior *gravityBehavior = [[UIGravityBehavior alloc] initWithItems:@[_square]];
gravityBehavior.magnitude = 0.1;
[_animator addBehavior:gravityBehavior];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
_square.center = [touch locationInView:self.view];
NSLog(@"transform before rotation: %@", NSStringFromCGAffineTransform(_square.transform));
_square.transform = CGAffineTransformMakeRotation(M_PI/4);
[_animator updateItemUsingCurrentState:_square];
NSLog(@"transform after rotation: %@", NSStringFromCGAffineTransform(_square.transform));
}
@end
(I've left here all code, so that you can copy-paste it into a newly created project. Hopefully there isn't too much of irrelevant code to make it disturbing)
So am I doing something wrong? Or isn't it possible to explicitly change rotation of the view?
Based on Infinity James' answer I found a solution that works quite well.
So to update an item's rotation you need to
1. remove all behaviors that affect the item from the dynamic animator
2. update the item's rotation
3. return the removed behaviors back to the animator (there's no need to create new behaviors)
Note: You could add all behaviors to one parent behavior as child behaviors, so you can remove and return all of them at once (but this attitude stops all the movement in dynamic animator, so you should consider also other less harming ways).
- (void)rotateItem:(UICollectionViewLayoutAttributes *)item toAngle:(CGFloat)angle
{
CGPoint center = item.center;
[self.dynamicAnimator removeBehavior:self.parentBehavior];
item.transform = CGAffineTransformMakeRotation(angle);
[self.dynamicAnimator addBehavior:self.parentBehavior];
}
This solution is a kind of compromise, since it stops movement of the item, so please add your answer if you find something better...