Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When implementing custom view controller presentations, where to apply presented view's constraints?

When presenting a view controller using a custom animation, none of Apple's documentation or example code mentions or includes constraints, beyond the following:

// Always add the "to" view to the container.
// And it doesn't hurt to set its start frame.
[containerView addSubview:toView];
toView.frame = toViewStartFrame;

The problem is that the double-height status bar is not recognized by custom-presented view controllers (view controllers that use non-custom presentations don't have this problem). The presented view controller is owned by the transition's container view, which is a temporary view provided by UIKit that we have next to no dominion over. If we anchor the presented view to that transient container, it only works on certain OS versions; not to mention, Apple has never suggested doing this.

UPDATE 1: There is no way to consistently handle a double-height status bar with custom modal presentations. I think Apple botched it here and I suspect they will eventually phase it out.

UPDATE 2: The double-height status bar has been phased out and no longer exists on non-edge-to-edge devices.

like image 729
liquid LFG UKRAINE Avatar asked Nov 04 '18 18:11

liquid LFG UKRAINE


People also ask

What is presentation controller?

The presentation controller's role during all of these phases is to manage its own custom views and state information. During the presentation and dismissal phases, the presentation controller adds its custom views (if any) to the view hierarchy and creates any appropriate transition animations for those views.

How do I get the presenting view controller?

Set the modalPresentationStyle property of the new view controller to the desired presentation style. Set the modalTransitionStyle property of the view controller to the desired animation style. Call the presentViewController:animated:completion: method of the current view controller.

What is modalPresentationStyle?

Presentation style defines how the system presents a modal view controller. The system uses this value only in regular-width size classes. In compact-width size classes, some styles take on the behavior of other styles.


1 Answers

My answer is: You should not use constraints in case of custom modal presentations

Therefore I know your pain, so I will try to help you to save time and effort by providing some hints which I suddenly revealed.


Example case:

Card UI animation like follows:

enter image description here

Terms for further use:

  • Parent - UIViewController with "Detail" bar button item
  • Child - UIViewController with "Another"

Troubles you mentioned began, when my animation involved size change along with the movement. It causes different kinds of effects including:

  • Parent's under-status-bar area appeared and disappeared
  • Parent's subviews were animated poorly - jumps, duplication and other glitches.

After few days of debugging and searching I came up with the following solution (sorry for some magic numbers ;)):

UIView.animate(withDuration: transitionDuration(using: transitionContext),
                       delay: 0,
                       usingSpringWithDamping: 1,
                       initialSpringVelocity: 0.4,
                       options: .curveEaseIn, animations: {
            toVC.view.transform = CGAffineTransform(translationX: 0, y: self.finalFrame.minY)
            toVC.view.frame = self.finalFrame
            toVC.view.layer.cornerRadius = self.cornerRadius
            
            fromVC.view.layer.cornerRadius = self.cornerRadius
            var transform = CATransform3DIdentity
            transform = CATransform3DScale(transform, scale, scale, 1.0)
            transform = CATransform3DTranslate(transform, 0, wdiff, 0)
            fromVC.view.layer.transform = transform
            fromVC.view.alpha = 0.6
        }) { _ in
            transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
        }

Main point here is, that You have to use CGAffineTransform3D to avoid animation problems and problems with subviews animation (2D Transforms are not working for unknown reasons).

This approach fixes, I hope, all your problems without using constraints.

Feel free to ask questions.

UPD: According to In-Call status bar

After hours of all possible experiments and examining similar projects like this and this and stackoverflow questions like this, this (it's actually fun, OPs answer is there) and similar I am totally confused. Seems like my solution handles Double status bar on UIKit level (it adjusts properly), but the same movement is ignoring previous transformations. The reason is unknown.


Code samples:

You can see the working solution here on Github

P.S. I'm not sure if it's ok to post a GitHub link in the answer. I'd appreciate for an advice how to post 100-300 lines code In the answer.

like image 50
fewlinesofcode Avatar answered Sep 20 '22 15:09

fewlinesofcode