我希望欢迎视图控制器和 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)
}
}
使用
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()
}
}