Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIDynamics and Autolayout

Recently I used UIDynamics to animate an image view into place. However, because its autolayout y-pos constraint was set to off-screen, when navigating away from the screen and then returning to it, my image view was being placed off-screen again. The animation took about 3 seconds, so after three seconds I just reset the constraint. That feels a little hacky.

So my question is this: what is the proper way to handle autolayout and UIDynamics at the same time?

like image 752
jancakes Avatar asked Feb 14 '23 10:02

jancakes


2 Answers

This is not really a dynamics problem. Autolayout is incompatible with any view animation, or any manual setting of the frame: when layout comes along, it is the constraints that will be obeyed. It is up to you, if you move a view manually in any way, to update the constraints to match its new position/size/whatever.

Having said that: with UIKit Dynamics, when the animation ends, the animator will pause, and the animator's delegate is notified:

https://developer.apple.com/library/ios/documentation/uikit/reference/UIDynamicAnimatorDelegate_Protocol/Reference/Reference.html#//apple_ref/occ/intfm/UIDynamicAnimatorDelegate/dynamicAnimatorDidPause:

So that is the moment to update the constraints.

like image 163
matt Avatar answered Feb 16 '23 04:02

matt


You have a nice solution provided by Geppy Parziale in this tutorial.

Basically you can create an object that conforms to UIDynamicItem:

@interface DynamicHub : NSObject <UIDynamicItem>
    @property(nonatomic, readonly) CGRect bounds;
    @property(nonatomic, readwrite) CGPoint center;
    @property(nonatomic, readwrite) CGAffineTransform transform;
@end

That needs to init the bounds or it will crash:

- (id)init {
    self = [super init];
    if (self) {
        _bounds = CGRectMake(0, 0, 100, 100);
    }
    return self;
}

And then you use UIDynamics on that object and use the intermediate values to update your constraints:

DynamicHub *dynamicHub = [[DynamicHub alloc] init];

UISnapBehavior *snapBehavior = [[UISnapBehavior alloc] initWithItem:dynamicHub
                                           snapToPoint:CGPointMake(50.0, 150.0)];
[snapBehavior setDamping:.1];

snapBehavior.action = ^{
     self.firstConstraint.constant = [dynamicHub center].y;
     self.secondConstraint.constant = [dynamicHub center].x;
};

[self.animator addBehavior:snapBehavior];
like image 28
Tiago Almeida Avatar answered Feb 16 '23 04:02

Tiago Almeida