3

I'm modifying this example of using dynamic animators for view controller transitions. One of the things I want to do is make it work on iPad and change the direction of gravity transition from top down to right to left. I'm interested if there is a way for me to calculate the time of a view transition, based on view size, force applied and gravity direction? In other words, how long till a view hits the right boundary and stops bouncing off it.

I want to return this correct duration from:

- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext

The example I'm working with has push magnitude set to 100, which works for iPhone screens, but is "too slow" for an iPad screen. From what I understand, the force gets applied to a screen size, where iPad screen requires stronger push to move it in time.

So I modified the code as follows:

pushBehavior.pushDirection = CGVectorMake(1,0);
pushBehavior.magnitude = 700.0;
UIGravityBehavior *gravityBehavior = [[UIGravityBehavior alloc] initWithItems:@[toViewController.view]];
gravityBehavior.gravityDirection = CGVectorMake(-1.0, 0);

Which works, but now I don't know how long the new transition takes. The default value is 1.5 seconds, which works, but if I set it to 0.7s, the view gets stuck half way through transition.

- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext {
    return 1.5f;
}


- (UIDynamicAnimator*)animateForTransitionContext:(id<UIViewControllerContextTransitioning>)transitionContext {
    // Get the view controllers for the transition
    UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];


    // Prepare the view of the toViewController
    toViewController.view.frame = CGRectOffset(fromViewController.view.frame, 1.0f*fromViewController.view.frame.size.width,0);


    // Add the view of the toViewController to the containerView
    [[transitionContext containerView] addSubview:toViewController.view];

    // Create animator
    UIDynamicAnimator *animator = [[UIDynamicAnimator alloc] initWithReferenceView:[transitionContext containerView]];

    // Add behaviors
    UIGravityBehavior *gravityBehavior = [[UIGravityBehavior alloc] initWithItems:@[toViewController.view]];
    gravityBehavior.gravityDirection = CGVectorMake(-1.0, 0);

    UICollisionBehavior *collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[toViewController.view]];


    [collisionBehavior addBoundaryWithIdentifier:@"LeftBoundary" fromPoint:CGPointMake(0,0) toPoint:CGPointMake(0.0f, fromViewController.view.frame.size.height+1)];


    UIDynamicItemBehavior *propertiesBehavior = [[UIDynamicItemBehavior alloc] initWithItems:@[toViewController.view]];
    propertiesBehavior.elasticity = 0.2;

    UIPushBehavior *pushBehavior = [[UIPushBehavior alloc] initWithItems:@[toViewController.view] mode:UIPushBehaviorModeInstantaneous];
//    pushBehavior.angle = 0;
    pushBehavior.pushDirection = CGVectorMake(-1, 0);
    pushBehavior.magnitude = 700.0;

    [animator addBehavior:pushBehavior];
    [animator addBehavior:propertiesBehavior];
    [animator addBehavior:collisionBehavior];
    [animator addBehavior:gravityBehavior];

    return animator;
}
Alex Stone
  • 46,408
  • 55
  • 231
  • 407
  • I believe this is impossible at least right now. Unless apple provides the transitioning protocol which doesn't require `transitionDuration` – hasrthur Mar 07 '15 at 18:47

1 Answers1

0

UIDynamicAnimator has this delegate method: dynamicAnimatorDidPause: When the views reach a static state, it will be called. So put a reference to transitionContext (like a weak property), set the animator delegate to self and call completeTransition:.

-(void)dynamicAnimatorDidPause:(UIDynamicAnimator *)animator
{
    [self.transitionContext completeTransition:finished];
}