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

如何在UIPageViewController翻页转场时同步实现视图位移动画?

问题:iOS 16+ 同时实现翻页转场与X轴位移动画异常

需求与现有实现

需要同时实现翻页转场(page curl)和X轴位移动画(横屏录制时位移表现为Y轴方向):

  • 翻页转场通过调用UIPageViewController的setViewControllers方法触发系统自带动画
  • 位移动画通过UIView.animate更新约束的方式实现

异常表现

该实现在iOS 15及更早版本运行正常,但iOS 16之后出现动画卡顿且不符合预期:

  • 无位移的常规翻页转场:页面背面完全可见(与iOS14/15带位移时的正常表现一致)
  • 带X轴位移的翻页转场:页面背面部分区域透明,慢动作下可清晰看到本该显示红色的区域变成了透明;但无位移时翻页动画完全正常

核心疑问

  1. 如何正确实现翻页转场与X轴位移动画的同步执行?
  2. 为何该异常仅在iOS新版本中出现?

复现代码(仅支持横屏)

import UIKit

final class ViewController: UIViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
    
    private var pageController: UIPageViewController?
    private var pageControllerViewLeadingAnchor: NSLayoutConstraint?

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 初始化UIPageViewController
        pageController = UIPageViewController(transitionStyle: .pageCurl, navigationOrientation: .horizontal, options: nil)
        pageController?.dataSource = self
        pageController?.delegate = self
        
        // 添加子控制器
        addChild(pageController!)
        view.addSubview(pageController!.view)
        
        // 设置约束
        pageController?.view.translatesAutoresizingMaskIntoConstraints = false
        pageController?.view.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        pageController?.view.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
        pageControllerViewLeadingAnchor = pageController?.view.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: -view.bounds.width/4)
        pageControllerViewLeadingAnchor?.isActive = true
        pageController?.view.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
    }
        
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        DispatchQueue.main.asyncAfter(deadline: .now()+0.5) {
            
            // 执行X轴位移动画
            UIView.animate(withDuration: 0.3, animations: {
                self.pageControllerViewLeadingAnchor?.constant = 0
                self.view.layoutIfNeeded()
            })
            
            // 执行翻页转场动画
            let vc = UIViewController()
            let vc2 = UIViewController()
            vc.view.backgroundColor = .red
            vc2.view.backgroundColor = .blue
            self.pageController?.setViewControllers([vc, vc2], direction: .forward, animated: true, completion: nil)
        }
    }

    func pageViewController(_ pageViewController: UIPageViewController, spineLocationFor orientation: UIInterfaceOrientation) -> UIPageViewController.SpineLocation {
        
        // 设置书脊在中间,添加初始控制器
        let vc = UIViewController()
        let vc2 = UIViewController()
        vc2.view.backgroundColor = .green
        pageController?.setViewControllers([vc, vc2], direction: .forward, animated: true, completion: nil)
        pageController?.isDoubleSided = true
        return .mid
    }
    
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        return UIViewController()
    }
    
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        return UIViewController()
    }

}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 09:02:03