Ant*_*ton 30 uiviewcontroller presentmodalviewcontroller ios swift
我试图在其他viewController上呈现模态视图控制器大小到半父视图控制器.但它始终以全屏视图显示.
我在我的故事板中创建了具有固定帧大小的自由形式大小的View控制器.320 X 250.
var storyboard = UIStoryboard(name: "Main", bundle: nil)
var pvc = storyboard.instantiateViewControllerWithIdentifier("CustomTableViewController") as ProductsTableViewController
self.presentViewController(pvc, animated: true, completion: nil)
Run Code Online (Sandbox Code Playgroud)
我试图设置frame.superview,它没有帮助.

请指教.
小智 66
您可以使用a UIPresentationController来实现此目的.
为此,您可以使用演示ViewController工具UIViewControllerTransitioningDelegate并返回您PresentationController的半尺寸演示文稿:
func presentationControllerForPresentedViewController(presented: UIViewController, presentingViewController presenting: UIViewController!, sourceViewController source: UIViewController) -> UIPresentationController? {
return HalfSizePresentationController(presentedViewController: presented, presentingViewController: presenting)
}
Run Code Online (Sandbox Code Playgroud)
在演示时,您将演示文稿样式.Custom设置为并设置转换委托:
pvc.modalPresentationStyle = UIModalPresentationStyle.Custom
pvc.transitioningDelegate = self
Run Code Online (Sandbox Code Playgroud)
演示控制器仅返回您呈现的视图控制器的帧:
class HalfSizePresentationController : UIPresentationController {
override func frameOfPresentedViewInContainerView() -> CGRect {
return CGRect(x: 0, y: containerView.bounds.height/2, width: containerView.bounds.width, height: containerView.bounds.height/2)
}
}
Run Code Online (Sandbox Code Playgroud)
以下是完整的工作代码:
class ViewController: UIViewController, UIViewControllerTransitioningDelegate {
@IBAction func tap(sender: AnyObject) {
var storyboard = UIStoryboard(name: "Main", bundle: nil)
var pvc = storyboard.instantiateViewControllerWithIdentifier("CustomTableViewController") as UITableViewController
pvc.modalPresentationStyle = UIModalPresentationStyle.Custom
pvc.transitioningDelegate = self
pvc.view.backgroundColor = UIColor.redColor()
self.presentViewController(pvc, animated: true, completion: nil)
}
func presentationControllerForPresentedViewController(presented: UIViewController, presentingViewController presenting: UIViewController!, sourceViewController source: UIViewController) -> UIPresentationController? {
return HalfSizePresentationController(presentedViewController: presented, presentingViewController: presentingViewController)
}
}
class HalfSizePresentationController : UIPresentationController {
override func frameOfPresentedViewInContainerView() -> CGRect {
return CGRect(x: 0, y: containerView.bounds.height/2, width: containerView.bounds.width, height: containerView.bounds.height/2)
}
}
Run Code Online (Sandbox Code Playgroud)
Khu*_*ong 29
如果你UIViewControllerTransitioningDelegate在ViewController中推送一些希望出现半模态的委托方法,那将是一个干净的架构师.
假设我们ViewControllerA现在ViewControllerB有一半的模式.
在ViewControllerA目前ViewControllerB与自定义modalPresentationStyle
func gotoVCB(_ sender: UIButton) {
let vc = ViewControllerB()
vc.modalPresentationStyle = .custom
present(vc, animated: true, completion: nil)
}
Run Code Online (Sandbox Code Playgroud)
在ViewControllerB中:
import UIKit
final class ViewControllerB: UIViewController {
lazy var backdropView: UIView = {
let bdView = UIView(frame: self.view.bounds)
bdView.backgroundColor = UIColor.black.withAlphaComponent(0.5)
return bdView
}()
let menuView = UIView()
let menuHeight = UIScreen.main.bounds.height / 2
var isPresenting = false
init() {
super.init(nibName: nil, bundle: nil)
modalPresentationStyle = .custom
transitioningDelegate = self
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .clear
view.addSubview(backdropView)
view.addSubview(menuView)
menuView.backgroundColor = .red
menuView.translatesAutoresizingMaskIntoConstraints = false
menuView.heightAnchor.constraint(equalToConstant: menuHeight).isActive = true
menuView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
menuView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
menuView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(ViewControllerB.handleTap(_:)))
backdropView.addGestureRecognizer(tapGesture)
}
func handleTap(_ sender: UITapGestureRecognizer) {
dismiss(animated: true, completion: nil)
}
}
extension ViewControllerB: UIViewControllerTransitioningDelegate, UIViewControllerAnimatedTransitioning {
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return self
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return self
}
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 1
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let containerView = transitionContext.containerView
let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)
guard let toVC = toViewController else { return }
isPresenting = !isPresenting
if isPresenting == true {
containerView.addSubview(toVC.view)
menuView.frame.origin.y += menuHeight
backdropView.alpha = 0
UIView.animate(withDuration: 0.4, delay: 0, options: [.curveEaseOut], animations: {
self.menuView.frame.origin.y -= self.menuHeight
self.backdropView.alpha = 1
}, completion: { (finished) in
transitionContext.completeTransition(true)
})
} else {
UIView.animate(withDuration: 0.4, delay: 0, options: [.curveEaseOut], animations: {
self.menuView.frame.origin.y += self.menuHeight
self.backdropView.alpha = 0
}, completion: { (finished) in
transitionContext.completeTransition(true)
})
}
}
}
Run Code Online (Sandbox Code Playgroud)
结果:
所有代码都发布在我的Github上
Fra*_*eau 17
以防万一有人希望像我一样使用Swift 4.
class MyViewController : UIViewController {
...
@IBAction func dictionaryButtonTouchUp(_ sender: UIButton) {
let modalViewController = ...
modalViewController.transitioningDelegate = self
modalViewController.modalPresentationStyle = .custom
self.present(modalViewController, animated: true, completion: nil)
}
}
extension MyViewController : UIViewControllerTransitioningDelegate {
func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
return HalfSizePresentationController(presentedViewController: presented, presenting: presenting)
}
}
Run Code Online (Sandbox Code Playgroud)
HalfSizePresentationController类由以下内容组成:
class HalfSizePresentationController : UIPresentationController {
override var frameOfPresentedViewInContainerView: CGRect {
get {
guard let theView = containerView else {
return CGRect.zero
}
return CGRect(x: 0, y: theView.bounds.height/2, width: theView.bounds.width, height: theView.bounds.height/2)
}
}
}
Run Code Online (Sandbox Code Playgroud)
干杯!
Jannis很好地抓住了整体战略.它在iOS 9.x中使用swift 3不起作用.在呈现VC时,启动所呈现的VC的操作类似于上面提到的一些非常小的更改,如下所示:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let pvc = storyboard.instantiateViewController(withIdentifier: "SomeScreen") as SomeViewController
pvc.modalPresentationStyle = .custom
pvc.transitioningDelegate = self
present(pvc, animated: true, completion: nil)
Run Code Online (Sandbox Code Playgroud)
要UIViewControllerTransitioningDelegate在同一个演示VC上实现,语法是完全不同的,如/sf/answers/2765927321/中的SO答案中所突出显示的那样.这对我来说是最棘手的部分.这是协议实现:
func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
return HalfSizePresentationController(presentedViewController:presented, presenting: presenting)
}
Run Code Online (Sandbox Code Playgroud)
对于UIPresentationController类,我必须覆盖变量frameOfPresentedViewInContainerView,而不是方法,如下所示:
class HalfSizePresentationController: UIPresentationController {
override var frameOfPresentedViewInContainerView: CGRect {
return CGRect(x: 0, y: 0, width: containerView!.bounds.width, height: containerView!.bounds.height/2)
}
}
Run Code Online (Sandbox Code Playgroud)
关于如何在演示后解雇视图存在一些问题.您可以像任何其他VC一样在您呈现的VC上实现所有常用逻辑.SomeViewController当用户在显示的VC之外选中时,我实现了一个动作来关闭视图.
主意:
隐藏root view并ChildViewController添加将用作 的新视图root view。
主要逻辑:
class ChildViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .clear
let contentView = UIView()
contentView.backgroundColor = .lightGray
view.addSubview(contentView)
//...
}
}
Run Code Online (Sandbox Code Playgroud)
import UIKit
// MARK: ParentViewController
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)
}
}
// MARK: ChildViewController
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
}
}
Run Code Online (Sandbox Code Playgroud)
主意:
更改 的根视图的大小ChildViewController。
主要逻辑:
模态呈现控制器
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) }
}
}
Run Code Online (Sandbox Code Playgroud)
更新根视图大小
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)
}
}
Run Code Online (Sandbox Code Playgroud)
不要忘记将
ModalPresentationController上面定义的内容粘贴到此处
import UIKit
// MARK: ParentViewController
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)
}
}
// MARK: ChildViewController
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)
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
40492 次 |
| 最近记录: |