详情
- Xcode 12.2 (12B45b)
- Swift 5.3
解决方案1:默认转换
思路:
隐藏ChildViewController
的root view
,并添加新视图作为root view
。
主要逻辑:
class ChildViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .clear
let contentView = UIView()
contentView.backgroundColor = .lightGray
view.addSubview(contentView)
}
}
解决方案1. 全样本
import UIKit
class ParentViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton(frame: CGRect(x: 50, y: 50, width: 200, height: 60))
button.setTitle("Present VC", for: .normal)
button.setTitleColor(.blue, for: .normal)
button.addTarget(self, action: #selector(touchedUpInside), for: .touchUpInside)
view.addSubview(button)
}
@objc func touchedUpInside(source: UIButton) {
let viewController = ChildViewController()
present(viewController, animated: true, completion: nil)
}
}
class ChildViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .clear
let contentView = UIView()
contentView.backgroundColor = .lightGray
view.addSubview(contentView)
contentView.translatesAutoresizingMaskIntoConstraints = false
contentView.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.5).isActive = true
contentView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor).isActive = true
contentView.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor).isActive = true
contentView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
}
}
解决方案 2. 自定义转场
思路:
改变ChildViewController
的根视图大小。
主要逻辑:
ModalPresentationController(模态呈现控制器)
protocol ModalPresentationControllerDelegate: class {
func updateFrameOfPresentedViewInContainerView(frame: CGRect) -> CGRect
}
class ModalPresentationController: UIPresentationController {
private weak var modalPresentationDelegate: ModalPresentationControllerDelegate!
convenience
init(delegate: ModalPresentationControllerDelegate,
presentedViewController: UIViewController,
presenting presentingViewController: UIViewController?) {
self.init(presentedViewController: presentedViewController,
presenting: presentingViewController)
self.modalPresentationDelegate = delegate
}
override var frameOfPresentedViewInContainerView: CGRect {
get { modalPresentationDelegate.updateFrameOfPresentedViewInContainerView(frame: super.frameOfPresentedViewInContainerView) }
}
}
更新根视图大小。
class ChildViewController: UIViewController {
init() {
transitioningDelegate = self
modalPresentationStyle = .custom
}
}
extension ChildViewController: UIViewControllerTransitioningDelegate {
func presentationController(forPresented presented: UIViewController,
presenting: UIViewController?,
source: UIViewController) -> UIPresentationController? {
ModalPresentationController(delegate: self, presentedViewController: presented, presenting: presenting)
}
}
extension ChildViewController: ModalPresentationControllerDelegate {
func updateFrameOfPresentedViewInContainerView(frame: CGRect) -> CGRect {
CGRect(x: 0, y: frame.height/2, width: frame.width, height: frame.height/2)
}
}
解决方案 2. 完整示例
不要忘记在此处粘贴上方定义的ModalPresentationController
import UIKit
class ParentViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton(frame: CGRect(x: 50, y: 50, width: 200, height: 60))
button.setTitle("Present VC", for: .normal)
button.setTitleColor(.blue, for: .normal)
button.addTarget(self, action: #selector(touchedUpInside), for: .touchUpInside)
view.addSubview(button)
}
@objc func touchedUpInside(source: UIButton) {
let viewController = ChildViewController()
present(viewController, animated: true, completion: nil)
}
}
class ChildViewController: UIViewController {
init() {
super.init(nibName: nil, bundle: nil)
transitioningDelegate = self
modalPresentationStyle = .custom
view.backgroundColor = .lightGray
}
required init?(coder: NSCoder) { super.init(coder: coder) }
}
extension ChildViewController: UIViewControllerTransitioningDelegate {
func presentationController(forPresented presented: UIViewController,
presenting: UIViewController?,
source: UIViewController) -> UIPresentationController? {
ModalPresentationController(delegate: self, presentedViewController: presented, presenting: presenting)
}
}
extension ChildViewController: ModalPresentationControllerDelegate {
func updateFrameOfPresentedViewInContainerView(frame: CGRect) -> CGRect {
CGRect(x: 0, y: frame.height/2, width: frame.width, height: frame.height/2)
}
}