Question

I like that UISnapBehavior snippet, but I really want to use it to slide in one direction only with a slight oscillation.

Is there a way to turn off rotation for this behavior? As SpriteKit has allowsRotation property which can be easily turned off.

Was it helpful?

Solution

You can do this by adding a UIDynamicItemBehavior to your UIDynamicAnimator and then setting its allowsRotation property to NO like so:

UIDynamicItemBehavior * dynamicItem = [[UIDynamicItemBehavior alloc] initWithItems:@[self.viewToSnap]];
dynamicItem.allowsRotation = NO;
[self.animator addBehavior:dynamicItem];

OTHER TIPS

Here's a better answer: A UISnapBehavior has an action property, which takes a block which gets called at every step. Setting this block like this...

snapBehavior.action = ^{ view.transform = CGAffineTransformIdentity; };

... causes the rotation to be nulled without any other side effects.

No need for UIKitDynamics for this.

Just simply had to use:

[UIView animateWithDuration:0.5
                          delay:0.0
         usingSpringWithDamping:0.65
          initialSpringVelocity:0.5
                        options:0
                     animations:^
    {
        self.transform = (self.expanded) ? self.openedTransition : self.closedTransition;
    }
                      completion:nil];

I was looking for the same solution myself, but setting allowsRotation on a UIDynamicItemBehavior didn't quite give me the effect I was looking for.

I was able to prevent any movement from UISnapBehavior by placing using UICollisionBehavior and placing two boundaries on either side of the view I didn't want to move (in my case, I configured boundaries on left and right side of the view to prevent x-axis movement). To get a nice bouncy effect I also set friction to 0 (using UIDynamicItemBehavior) and adjusted the damping on UISnapBehavior to get the right amount of bounce.

Here's an example of what worked for me:

[self.animator removeAllBehaviors];

UISnapBehavior *snapBackBehavior = [[UISnapBehavior alloc] initWithItem:self.snappingView snapToPoint:self.slidePanelCenter];
snapBackBehavior.damping = 0.2;
[self.animator addBehavior:snapBackBehavior];

UIDynamicItemBehavior *itemBehavior = [[UIDynamicItemBehavior alloc] initWithItems:@[self.snappingView]];
itemBehavior.friction = 0.0;
[self.animator addBehavior:itemBehavior];

CGPoint leftBoundaryStart  = CGPointMake(self.snappingView.frame.origin.x, 0.0);
CGPoint leftBoundaryEnd    = CGPointMake(leftBoundaryStart.x, self.view.bounds.size.height);
CGPoint rightBoundaryStart = CGPointMake(leftBoundaryStart.x + self.snappingView.frame.size.width, 0.0);
CGPoint rightBoundaryEnd   = CGPointMake(rightBoundaryStart.x, leftBoundaryEnd.y);

UICollisionBehavior *collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[self.snappingView]];
[collisionBehavior addBoundaryWithIdentifier:@"leftEdge" fromPoint:leftBoundaryStart toPoint:leftBoundaryEnd];
[collisionBehavior addBoundaryWithIdentifier:@"rightEdge" fromPoint:rightBoundaryStart toPoint:rightBoundaryEnd];
[self.animator addBehavior:collisionBehavior];

UIView conforms to UIDynamicItem, which has a transform property that gets called when a rotation is made. So overriding setTransform: with nothingness...

- (void)setTransform:(CGAffineTransform)transform
{
}

... stops the rotation, but probably with unknown and undesirable side effects. Need some way to check if the dynamic animation is in progress.

There will still be some bouncy motion parallel to the direction of movement on the way to the new location.

It would be great if we could control the amount of the rotation/bouncy effect as it's quite cartoonish as is.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top