I want both the welcome view controller and ViewController2 to have a UIVisualEffectView for their background. When I push ViewController2, the animation is very glitchy and doesn't fully animate to the left during the push animation. Pop animation works fine. Is there anyway to fix this weird animation?
Minimum Reproducible Example is below
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)
}
}
When using a
UINavigationController, the default transition is not a direct "slide side-by-side." The controller views overlap and fade.You have a couple options...
UIPageViewControllerUIScrollViewas a "container" and load your view controllers as childrenWhich approach to use depends on a number of factors -- such as how many controllers you want to show, do you want interactive drag-to-slide, etc.
Probably the most straightforward approach would be the "container" approach.
Here's a complete, minimal example, based on your code: