Swift实现类似Facebook评论页的全屏导航推送转场
解决iOS模态呈现带导航栏的全屏转场(仿Facebook评论页效果)
我之前折腾过好多次这个需求!就是Facebook那种点击帖子后,评论页全屏滑出来的模态效果,连导航栏一起跟着转场动,而不是只弹出VC内部的内容对吧?给你两个亲测有效的实现方案:
方案一:自定义转场动画 + UINavigationController包裹
核心思路是把你的评论VC用导航控制器包裹,让整个导航控制器参与模态转场动画,而不是只动内部VC的视图:
- 先准备好你的评论ViewController,比如
CommentViewController,给它配置好导航栏的按钮、样式(比如设置navigationItem.title、leftBarButtonItem) - 创建自定义转场动画器,实现转场协议:
class FullScreenSlideAnimator: NSObject, UIViewControllerAnimatedTransitioning { // 转场时长,可根据需求调整 func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { return 0.35 } func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { guard let toNavVC = transitionContext.viewController(forKey: .to) as? UINavigationController, let toView = toNavVC.view else { return } let container = transitionContext.containerView // 初始位置设为屏幕右侧(如果要从底部滑入就改y值为container.height) toView.frame = CGRect(x: container.bounds.width, y: 0, width: container.bounds.width, height: container.bounds.height) container.addSubview(toView) UIView.animate(withDuration: transitionDuration(using: transitionContext), delay: 0, options: .curveEaseOut) { toView.frame = container.bounds } { finished in transitionContext.completeTransition(!transitionContext.transitionWasCancelled) } } }
- 在触发转场的VC里,设置模态的代理和样式:
// 实例化评论VC并包裹进导航控制器 let commentVC = CommentViewController() let navVC = UINavigationController(rootViewController: commentVC) // 设置自定义模态样式 navVC.modalPresentationStyle = .custom navVC.transitioningDelegate = self // 弹出模态VC present(navVC, animated: true)
- 让触发转场的VC遵守
UIViewControllerTransitioningDelegate,并返回自定义动画器:
extension YourSourceViewController: UIViewControllerTransitioningDelegate { func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { return FullScreenSlideAnimator() } }
方案二:利用iOS13+的PageSheet模态(更简单)
如果你的APP只需要支持iOS13及以上,这个方案几乎零成本:
直接把评论VC包裹进导航控制器,用系统的pageSheet模态样式,再配置成全屏展示:
let commentVC = CommentViewController() let navVC = UINavigationController(rootViewController: commentVC) if #available(iOS 13.0, *) { navVC.modalPresentationStyle = .pageSheet // 配置为全屏展示,隐藏底部抓手(可选) if let sheet = navVC.sheetPresentationController { sheet.detents = [.large()] sheet.prefersGrabberVisible = false sheet.largestUndimmedDetentIdentifier = .none // 背景完全变暗 } } else { // iOS13以下用全屏模态 navVC.modalPresentationStyle = .fullScreen } present(navVC, animated: true)
系统自带的转场动画会自动让整个导航栏跟着一起滑入,效果非常接近Facebook的样式,而且不需要写自定义动画代码。
关键注意点
- 绝对不要直接模态
CommentViewController然后在内部手动加导航栏!那样导航栏是VC的子视图,不会参与模态转场动画,必须用UINavigationController包裹后再模态。 - 如果需要自定义返回逻辑,在
CommentViewController里设置navigationItem.leftBarButtonItem,点击时调用dismiss(animated: true),这样按钮会跟着导航栏一起参与转场。
内容的提问来源于stack exchange,提问作者pmax1
相关产品推荐
相关产品推荐

