You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在UIPageViewController中实现自定义页面转场及3D立方体滑动转场

在UIPageViewController中实现自定义转场与3D立方体效果

一、是否支持自定义转场?

完全没问题!UIPageViewController提供了成熟的自定义转场能力,你可以通过两种方式实现:

  • 借助UIPageViewControllerDelegate的animationControllerForTransitionFrom:to:方法,返回自定义动画控制器;
  • 更灵活的方式是创建遵守UIViewControllerAnimatedTransitioning协议的动画类,全权控制转场逻辑。

二、实现3D立方体转场效果

你提到的“只操作下一页视图做3D变换”其实不是最优解——真正的立方体转场需要同时对当前页和目标页做3D变换,配合透视效果才能模拟出真实的立方体翻转质感。下面是具体实现步骤:

1. 创建自定义转场动画类

先写一个负责处理3D变换的动画类,核心是利用CATransform3D实现透视和旋转效果:

class CubePageTransitionAnimator: NSObject, UIViewControllerAnimatedTransitioning {
    private let isForwardTransition: Bool
    
    init(isForward: Bool) {
        self.isForwardTransition = isForward
        super.init()
    }
    
    // 设置动画时长
    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 0.6
    }
    
    // 核心动画逻辑
    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        let container = transitionContext.containerView
        guard let fromVC = transitionContext.viewController(forKey: .from),
              let toVC = transitionContext.viewController(forKey: .to) else {
            transitionContext.completeTransition(false)
            return
        }
        
        // 将目标视图添加到容器视图
        container.addSubview(toVC.view)
        
        // 设置透视效果,m34值越小,透视感越强(调整500这个数值可以改变透视程度)
        var perspectiveTransform = CATransform3DIdentity
        perspectiveTransform.m34 = -1 / 500.0
        container.layer.sublayerTransform = perspectiveTransform
        
        let direction: CGFloat = isForwardTransition ? 1 : -1
        // 定义当前页的最终旋转状态、目标页的初始旋转状态
        let fromFinalTransform = CATransform3DMakeRotation(direction * .pi/2, 0, 1, 0)
        let toInitialTransform = CATransform3DMakeRotation(-direction * .pi/2, 0, 1, 0)
        
        // 初始化视图的变换状态
        toVC.view.layer.transform = toInitialTransform
        fromVC.view.layer.transform = CATransform3DIdentity
        
        // 执行动画
        UIView.animate(withDuration: transitionDuration(using: transitionContext),
                       options: .curveEaseInOut) {
            fromVC.view.layer.transform = fromFinalTransform
            toVC.view.layer.transform = CATransform3DIdentity
        } { finished in
            // 重置当前页的变换,避免影响后续转场
            fromVC.view.layer.transform = CATransform3DIdentity
            transitionContext.completeTransition(finished && !transitionContext.transitionWasCancelled)
        }
    }
}

2. 在UIPageViewController代理中关联动画器

让你的UIPageViewController遵守UIPageViewControllerDelegate,并在代理方法中返回刚才创建的动画器:

extension YourPageViewController: UIPageViewControllerDelegate {
    func pageViewController(_ pageViewController: UIPageViewController, animationControllerForTransitionFrom fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        // 通过页面索引判断是向前还是向后翻页
        guard let fromIndex = yourPageViewControllers.firstIndex(of: fromVC),
              let toIndex = yourPageViewControllers.firstIndex(of: toVC) else {
            return nil
        }
        let isForward = toIndex > fromIndex
        return CubePageTransitionAnimator(isForward: isForward)
    }
}

3. 额外注意事项

  • 确保UIPageViewController的transitionStyle设置为.scroll(这是启用自定义转场的基础配置);
  • 透视参数m34可以根据需求调整,数值越小(比如-1/600),翻转的立体感越强;
  • 如果需要支持手势驱动的实时转场,还可以实现UIViewControllerInteractiveTransitioning协议,配合UIPanGestureRecognizer处理滑动过程中的动态变换。

三、是不是只能操作下一页视图?

当然不是!立方体转场的核心是模拟一个立方体的两个面同步翻转,所以必须同时对当前页(转出的面)和目标页(转入的面)做3D旋转,这样才能呈现出自然的立方体翻转效果。如果只操作下一页,视觉上会非常生硬,完全没有立方体的真实质感。

内容的提问来源于stack exchange,提问作者John

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:51:57