9

I have a UIViewController presenting another UIViewController. Both view controllers use topLayoutGuide and bottomLayoutGuide with Auto-Layout.

Everything is fine, with and without in-call bar. Or with or without custom transition...

But, when there is an in-call bar and a custom transition, the subview of my presented view controller is misplaced of 20px down (resulting in a clipped view at the bottom).

I checked and it's the topLayoutGuide and bottomLayoutGuide which are misplaced...

Here's the code of the transition :

#pragma mark - GETTER
- (CGFloat)presentationTopProgressValue {
    return __fromViewControllerView.y / __containerView.height;
}

#pragma mark - SETTER
- (void)set_context:(id<UIViewControllerContextTransitioning>)_context {
    __context = _context;
    __containerView = [__context containerView];

    __fromViewController = [__context viewControllerForKey:UITransitionContextFromViewControllerKey];
    __fromViewControllerView = [__fromViewController view];
    __toViewController = [__context viewControllerForKey:UITransitionContextToViewControllerKey];
    __toViewControllerView = [__toViewController view];
}

#pragma mark - TRANSITION
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {
    return self;
}

#pragma mark - ANIMATING
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
    self._context = transitionContext;

    UIDynamicAnimator *animator = [[UIDynamicAnimator alloc] initWithReferenceView:__containerView];

    UIGravityBehavior *gravityBehavior = [[UIGravityBehavior alloc] initWithItems:@[__fromViewControllerView]];
    gravityBehavior.gravityDirection = CGVectorMake(0, 5.0f);

    __weak typeof(self) weakSelf = self;
    gravityBehavior.action = ^{
        typeof(self) strongSelf = weakSelf;

        if ([strongSelf presentationTopProgressValue] > 1.0) {
            [animator removeAllBehaviors];

            [strongSelf._context completeTransition:YES];
            strongSelf._context = nil;
        }
    };

    [__containerView addSubview:__toViewControllerView];
    [__containerView addSubview:__fromViewControllerView];

    [animator addBehavior:gravityBehavior];
}

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

Here's the code of the presenting :

MPProfileViewController *next = [MPProfileViewController new];
MPNavigationController *nav = [[MPNavigationController alloc] initWithRootViewController:next];
#warning - The transition delegate create a wrong margin layout when in-call bar is active
nav.modalPresentationStyle = UIModalPresentationFullScreen;
nav.transitioningDelegate = __dragToDismiss;
[self.navigationController presentViewController:nav animated:YES completion:nil];
KSR
  • 1,699
  • 15
  • 22
Tancrede Chazallet
  • 7,035
  • 6
  • 41
  • 62

1 Answers1

0

When creating the views for your view hierarchy, you should always set the autoresizing properties of your views. When a view controller is displayed on screen, its root view is typically resized to fit the available space, which can vary depending on the window's current orientation and the presence of other interface elements such as the status bar. You can configure the autoresizing properties in Interface Builder using the inspector window or programmatically by modifying the autoresizesSubviews and autoresizingMask properties of each view. Setting these properties is also important if your view controller supports both portrait and landscape orientations. During an orientation change, the system uses these properties to reposition and resize the views automatically to match the new orientation. If your view controller supports auto layout and is a child of another view controller, you should call the view's setTranslatesAutoresizingMaskIntoConstraints: method to disable these constraints.