1

I'm attempting to animate a view into position in a view that's using UIDynamics. I'm not clear on the interaction between the Core Animation animations and UIDynamics but something's going on that I don't understand.

I have a test project with a view controller with a single view, a label, that starts at the bottom middle of the view and I'm trying to animate motion to the top middle.

// Create the label
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(160, 400, 100, 50)];
label.text = @"hello";
[self.view addSubview:label];

// Set up the animator and collision
self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];

UICollisionBehavior *collisionBehaviour = [[UICollisionBehavior alloc] initWithItems:@[ label ]];
[collisionBehaviour addBoundaryWithIdentifier:@"wall"
                                    fromPoint:CGPointMake(0, 50)
                                      toPoint:CGPointMake(320, 50)];
[self.animator addBehavior:collisionBehaviour];

// Animate the label 
[UIView animateWithDuration:1.0
                 animations:^{
                     label.frame = CGRectMake(160, 100, 320, 100);
                 }];

This is simply a line boundary at the top of the view, nowhere near either the start or end position of my animation. I don't see why it should affect the animation of the button into its initial position, but it does.

If I comment out the addBehaviour: call then the animation works fine. But when I add the behaviour, the animation goes to the wrong location. I don't understand why.

stevex
  • 5,589
  • 37
  • 52

3 Answers3

0

The reason why in your example the label moves left is because you are changing the width of the label from 100px to 320px and the text is right justified.

Now as for why it doesn't move up, when you add the UICollisionBehavior to the label, and then to the UIDynamicAnimator, the UIDynamicAnimator is now in charge of moving the label. When you try and animate it up, the animation goes off, then the UIDynamicAnimator sees the change and sets the center of the label back to what it originally was. You can see this for yourself if you subclass UILabel and NSLog on when the frame and center changes. If you override setCenter to just return your label moves upward.

If you want to move the label either;

  1. Don't attach a UICollisionBehavior to the label and animate it
  2. Also attach a UIDynamicItemBehavior to the label and then addLinearVelocity
odyth
  • 4,324
  • 3
  • 37
  • 45
0

You should not set any view's frame manually if that view is managed by a dynamic animator.
The reason why it works without calling -addBehavior: is that the dynamic animator doesn't care about the label until any of its behaviors references the label.

You can move the label manually and start the dynamic animator when the animation is finished, but the better approach is to use a UISnapBehavior to move your label to the desired position.

Also, if you change a view's frame that is managed by a dynamic animator you have to remove all behaviors associated with that view and add them again. You should set your label's initial size and only change it's position from there on, but not its size.

Fabian Kreiser
  • 8,307
  • 1
  • 34
  • 60
0

when you set frame of your view below that line write [self.animator updateItemUsingCurrentState:label];

Abhi
  • 593
  • 4
  • 8