UINavigationController 推送新视图控制器时出现动画故障

问题描述 投票:0回答:1

我希望欢迎视图控制器和 ViewController2 都有一个 UIVisualEffectView 作为背景。当我推动 ViewController2 时,动画非常不稳定,并且在推动动画期间没有完全向左移动。流行动画效果很好。有办法修复这个奇怪的动画吗?

最小可重现示例如下

class ViewController: UIViewController {
    override func loadView() {
        view = MKMapView()
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
    
    override func viewDidAppear(_ animated: Bool) {
        let welcomeVC = WelcomeViewController()
        let navigationController = UINavigationController(rootViewController: welcomeVC)
        navigationController.isModalInPresentation = true
        if let sheet = navigationController.sheetPresentationController {
            sheet.detents = [.custom { context in
                return 200
            }, .medium(), .large()]
            sheet.prefersGrabberVisible = true
            sheet.preferredCornerRadius = 15
            sheet.largestUndimmedDetentIdentifier = .large
        }
        
        present(navigationController, animated: true)
    }
}

class WelcomeViewController: UIViewController {
    override func viewDidLoad() {
        let blurEffect = UIBlurEffect(style: .systemThinMaterial)
        let blurEffectView = UIVisualEffectView(effect: blurEffect)
        blurEffectView.frame = view.bounds
        view.addSubview(blurEffectView)
        view.sendSubviewToBack(blurEffectView)
        
                
        let button = UIButton()
        button.setTitle("Go to View Controller 2", for: .normal)
        button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
        button.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(button)
        
        NSLayoutConstraint.activate([
            button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            button.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            button.widthAnchor.constraint(equalToConstant: 200),
            button.heightAnchor.constraint(equalToConstant: 44)
        ])
    }
    
    @objc func buttonTapped() {
        let vc2 = ViewController2()
        navigationController?.pushViewController(vc2, animated: true)
    }
}

class ViewController2: UIViewController {
    override func viewDidLoad() {
        let blurEffect = UIBlurEffect(style: .systemThinMaterial)
        let blurEffectView = UIVisualEffectView(effect: blurEffect)
        blurEffectView.frame = view.bounds
        view.addSubview(blurEffectView)
        view.sendSubviewToBack(blurEffectView)
        
        
        let button = UIButton()
        button.setTitle("Go back to Welcome VC", for: .normal)
        button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
        button.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(button)
        
        NSLayoutConstraint.activate([
            button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            button.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            button.widthAnchor.constraint(equalToConstant: 200),
            button.heightAnchor.constraint(equalToConstant: 44)
        ])
    }
    
    @objc func buttonTapped() {
        
        navigationController?.popViewController(animated: true)
    }
}
swift uiviewcontroller uikit uinavigationcontroller uivisualeffectview
1个回答
0
投票

使用

UINavigationController
时,默认过渡是不是直接“并排滑动”。控制器视图重叠和淡出。

您有几个选择...

  • 为您的导航控制器使用自定义转换
  • 嵌入
    UIPageViewController
  • 使用
    UIScrollView
    作为“容器”并将视图控制器作为子项加载

使用哪种方法取决于许多因素 - 例如您想要显示多少个控制器、您是否想要交互式拖动滑动等。

最直接的方法可能是“容器”方法。

这是一个基于您的代码的完整的、最小的示例:

class ExampleViewController: UIViewController {
    override func loadView() {
        view = MKMapView()
    }
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    override func viewDidAppear(_ animated: Bool) {
        let containerVC = ExampleContainerVC()
        containerVC.isModalInPresentation = true
        if let sheet = containerVC.sheetPresentationController {
            sheet.detents = [.custom { context in
                return 200
            }, .medium(), .large()]
            sheet.prefersGrabberVisible = true
            sheet.preferredCornerRadius = 15
            sheet.largestUndimmedDetentIdentifier = .large
        }
        present(containerVC, animated: true)
    }
}

protocol ContainerNavDelegate: AnyObject {
    func showV2()
    func showWelcome()
}

class ExampleContainerVC: UIViewController, ContainerNavDelegate {

    let scrollView = UIScrollView()
    let stackView = UIStackView()
    
    override func viewDidLoad() {

        let blurEffect = UIBlurEffect(style: .systemThinMaterial)
        let blurEffectView = UIVisualEffectView(effect: blurEffect)
        blurEffectView.frame = view.bounds
        view.addSubview(blurEffectView)
        
        scrollView.showsVerticalScrollIndicator = false
        scrollView.showsHorizontalScrollIndicator = false
        scrollView.isScrollEnabled = false

        stackView.translatesAutoresizingMaskIntoConstraints = false
        scrollView.addSubview(stackView)
        
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(scrollView)
        
        let g = view.safeAreaLayoutGuide
        let cg = scrollView.contentLayoutGuide
        let fg = scrollView.frameLayoutGuide
        
        NSLayoutConstraint.activate([
            
            scrollView.topAnchor.constraint(equalTo: g.topAnchor),
            scrollView.leadingAnchor.constraint(equalTo: g.leadingAnchor),
            scrollView.trailingAnchor.constraint(equalTo: g.trailingAnchor),
            scrollView.bottomAnchor.constraint(equalTo: g.bottomAnchor),
            
            stackView.topAnchor.constraint(equalTo: cg.topAnchor),
            stackView.leadingAnchor.constraint(equalTo: cg.leadingAnchor),
            stackView.trailingAnchor.constraint(equalTo: cg.trailingAnchor),
            stackView.bottomAnchor.constraint(equalTo: cg.bottomAnchor),
            stackView.heightAnchor.constraint(equalTo: fg.heightAnchor),
            
        ])
        
        let vc1 = WelcomeVC()
        addChild(vc1)
        stackView.addArrangedSubview(vc1.view)
        vc1.view.widthAnchor.constraint(equalTo: fg.widthAnchor).isActive = true
        vc1.didMove(toParent: self)

        let vc2 = SecondVC()
        addChild(vc2)
        stackView.addArrangedSubview(vc2.view)
        vc2.view.widthAnchor.constraint(equalTo: fg.widthAnchor).isActive = true
        vc2.didMove(toParent: self)

        vc1.navDelegate = self
        vc2.navDelegate = self
        
    }

    func showV2() {
        guard stackView.arrangedSubviews.count == 2 else { return }
        let v = stackView.arrangedSubviews[1]
        scrollView.scrollRectToVisible(v.frame, animated: true)
    }
    
    func showWelcome() {
        guard stackView.arrangedSubviews.count > 0 else { return }
        let v = stackView.arrangedSubviews[0]
        scrollView.scrollRectToVisible(v.frame, animated: true)
    }

}

class WelcomeVC: UIViewController {
    
    var navDelegate: ContainerNavDelegate?
    
    override func viewDidLoad() {

        view.backgroundColor = .clear

        let button = UIButton()
        button.setTitle("Go to View Controller 2", for: .normal)
        button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
        button.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(button)
        
        NSLayoutConstraint.activate([
            button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            button.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            button.widthAnchor.constraint(equalToConstant: 200),
            button.heightAnchor.constraint(equalToConstant: 44)
        ])
    }
    
    @objc func buttonTapped() {
        navDelegate?.showV2()
    }
}

class SecondVC: UIViewController {
    
    var navDelegate: ContainerNavDelegate?
    
    override func viewDidLoad() {

        view.backgroundColor = .clear

        let button = UIButton()
        button.setTitle("Go back to Welcome VC", for: .normal)
        button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
        button.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(button)
        
        NSLayoutConstraint.activate([
            button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            button.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            button.widthAnchor.constraint(equalToConstant: 200),
            button.heightAnchor.constraint(equalToConstant: 44)
        ])
    }
    
    @objc func buttonTapped() {
        navDelegate?.showWelcome()
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.