While I can't answer your question on *why you cant use .fullScreen for MFMessageComposeViewController, I can tell you that if you implement your own custom transition you will get the desired behavior.
This is how you set custom transition for the view controller :
var customTransitionDelegate = CustomTransition(presentAnimation: CustomActionSheetPresentationTransition(), dismissAnimation: CustomActionSheetDismissalTransition())
if (MFMessageComposeViewController.canSendText()) {
let controller = MFMessageComposeViewController()
controller.body = "Message Body"
controller.messageComposeDelegate = self
controller.modalPresentationStyle = .custom
controller.transitioningDelegate = customTransitionDelegate
self.present(controller, animated: true, completion: nil)
}
You should also conform to the delegate and check the result to dismiss it after the user clicked cancel if he did :
func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) {
switch result {
case .cancelled:
self.presentedViewController?.dismiss(animated: true, completion: nil)
default: break
}
}
The presentation logic
class CustomActionSheetPresentationTransition: NSObject, UIViewControllerAnimatedTransitioning {
private let duration = 0.6
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard let fromView = transitionContext.viewController(forKey: .from) else { return }
guard let toView = transitionContext.viewController(forKey: .to) else { return }
var screenOffUp = CGAffineTransform()
let container = transitionContext.containerView
screenOffUp = CGAffineTransform(translationX: 0, y: -fromView.view.frame.height)
toView.view.frame = CGRect(x: 0, y: UIScreen.main.bounds.height, width: fromView.view.frame.width, height: fromView.view.frame.height)
toView.view.center.x = container.center.x
container.addSubview(toView.view)
UIView.animate(withDuration: duration, delay: 0.0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0.8, options: [], animations: {
toView.view.transform = screenOffUp
}, completion: { (success) in
transitionContext.completeTransition(success)
})
}
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return duration
}
}
The dismissal logic
class CustomActionSheetDismissalTransition: NSObject, UIViewControllerAnimatedTransitioning {
private let duration = 0.8
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return duration
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard let fromView = transitionContext.viewController(forKey: .from) else { return }
let screenOffDown = CGAffineTransform(translationX: 0, y: fromView.view.frame.height)
UIView.animate(withDuration: duration, delay: 0.0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0.8, options: [], animations: {
fromView.view.transform = screenOffDown
}, completion: { (success) in
transitionContext.completeTransition(success)
})
}
}