iOS 从底部弹出指定高度的vc

182 阅读1分钟

Simulator Screen Recording - iPhone 15 Pro Max - 2024-05-11 at 11.24.51.gif

先放代码,我这边用展示页面高度的一半做示例: 先把需要配置的动画配好

class HalfHeightPresentationController : UIPresentationController{
    override var shouldRemovePresentersView: Bool {
        return false
    }
    override func containerViewWillLayoutSubviews() {
        super.containerViewWillLayoutSubviews()
        containerView?.backgroundColor = UIColor(hexString: "#000000")!.withAlphaComponent(0.5)
        presentedView?.frame = CGRect(x: 0, y: containerView!.bounds.height / 2, width: containerView!.bounds.width,height: containerView!.bounds.height / 2)
    }
}
class HalfHeightAnimationController: NSObject, UIViewControllerAnimatedTransitioning {
    var isPresenting: Bool
    
    init(isPresenting: Bool) {
        self.isPresenting = isPresenting
    }
    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 0.3
    }
    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        if isPresenting {
            presentAnimation(transitionContext: transitionContext)
        } else {
            dismissAnimation(transitionContext: transitionContext)
        }
    }
    private func presentAnimation(transitionContext: UIViewControllerContextTransitioning) {
        // 获取目标视图
        if let toView = transitionContext.view(forKey: .to) {
            // 添加视图到上下文视图
            transitionContext.containerView.addSubview(toView)
            // 设置初始状态
            toView.frame = transitionContext.containerView.bounds
            toView.transform = CGAffineTransform(translationX: 0, y: transitionContext.containerView.bounds.height / 2)
            // 动画
            UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: {
                toView.transform = CGAffineTransform.identity
            }, completion: { _ **in**
                transitionContext.completeTransition(**true**)
            })
        }
    }
    private func dismissAnimation(transitionContext: UIViewControllerContextTransitioning) {

        // 获取视图
        if let fromView = transitionContext.view(forKey: .from) {
            UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: {
                fromView.transform = CGAffineTransform(translationX: 0, y: transitionContext.containerView.bounds.height / 2)
            }, completion: { _ in
                fromView.removeFromSuperview()       transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
            })
        }
    }
}

然后在主页面实现自定义的present方法与相关的代理方法

func presentViewControllerWithHalfHeight(viewController: UIViewController) {
       // 设置转场动画的 present 过程
        viewController.modalPresentationStyle = .custom
        viewController.transitioningDelegate = self
        // 执行 present 操作
        present(viewController, animated: true, completion: nil)
    }
    func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
        return HalfHeightPresentationController(presentedViewController: presented, presenting: presenting)
    }
    func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return* HalfHeightAnimationController(isPresenting: true)
    }
    func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return HalfHeightAnimationController(isPresenting: false)
    }

最后使用自定义present方法唤起页面就行