I'm pretty new to auto layout and I'm confused about how to animate views.
I read a lot, and I know you must hold to the constraints, edit it, and wrap the layoutIfNeeded
in an UIView
animation block.
But when it comes to do it, I'm a little lost. I'd love if someone could explain me how this animation is done for example.
I think it probably uses a UIPanGestureRecognizer
to change the constant
of the leading space to container constraint, but it probably uses UIDynamics (for the bounce effect at the right ?).
Well, similar behavior could be achieved with UIPanGestureRecognizer
+ [UIView animateWithDuration:animations:]
. Yes, you set leading space constraint and change it according to UIPanGestureRecognizer
state. Remember that you need to set final constraints only (define final position of a slider). Intermediate animation positions are calculated for you. For the slider we have default left position and activated middle position.
For view rotation we can use transform
property of UIView
.
Autolayout constraints in IB:
Setting animation options (UIViewAnimationOptionCurveEaseOut
animation curve) could give a feel of bounce effect. UIPanGestureRecognizer
code (omit instance variables declaration, because their names are self-explanatory):
- (IBAction)onPan:(UIPanGestureRecognizer*)sender
{
switch (sender.state) {
case UIGestureRecognizerStateBegan:
_startOffset = self.leadingSpace.constant;
_maxOffset = self.slider.superview.frame.size.width
- kHorizontalPadding
- self.slider.frame.size.width;
break;
case UIGestureRecognizerStateChanged: {
CGFloat offset = _startOffset + [sender translationInView:self.slider.superview].x;
offset = MIN(offset, _maxOffset);
self.leadingSpace.constant = offset;
break;
}
case UIGestureRecognizerStateEnded: {
CGFloat offset = _startOffset + [sender translationInView:sender.view.superview].x;
UIColor *bgColor = [UIColor lightGrayColor];
CGFloat rotation = 0;
if (offset < _maxOffset) {
offset = kHorizontalPadding;
}
else {
offset = (_maxOffset + kHorizontalPadding)/2;
bgColor = [UIColor redColor];
rotation = M_PI_2;
}
self.leadingSpace.constant = offset;
[UIView
animateWithDuration:.5
delay:0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
[self.slider layoutIfNeeded];
self.slider.backgroundColor = bgColor;
self.slider.transform = CGAffineTransformMakeRotation(rotation);
} completion:nil];
break;
}
default:
break;
}
}
Animation result with UIViewAnimationOptionCurveLinear
(capture simulator):
Animation result with UIViewAnimationOptionCurveEaseOut
(capture simulator):
UIDynamics
With UIDynamics things become more complicated. Good starting point is Ray Wenderlich UIKit Dynamics Tutorial.
For bouncing slider we could add following behaviors:
UIGravityBehavior
which pulls a slider to start position. We need to change angle
property to direct gravity force to the left.UICollisionBehavior
which defines left and right edges of allowed movements. translatesReferenceBoundsIntoBoundary
property will be useful if we treat parent view as boundary. Also we need to add extra boundary to stop slider in the middle using addBoundaryWithIdentifier:fromPoint:toPoint
(or bezier path).UIDynamicItemBehavior
to change elasticy
and possibly resistance
properties to configure bounce and acceleration respectively.UIPushBehavior
in conjunction with recognizer's velocityInView:
to specify slider velocity when a user releases a sliderUISnapBehavior
as an alternative to UIGravityBehavior
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With