我有一个 UIViewController
,它只有一个 UIView
,它从底部覆盖了 1/3 的 viewController。像这样
我想在另一个 ViewController 上显示这个 viewController。它应该从底部动画出现,并且应该消失到底部动画。
但我不希望它覆盖整个屏幕。显示它的 viewController 应该在后面可见。
这似乎是一个基本问题,但我无法完成它。有人可以给我指个方向吗?
编辑:
这是我迄今为止尝试过的。我创建了这些类
// MARK: -
class MyFadeInFadeOutTransitioning: NSObject, UIViewControllerTransitioningDelegate {
var backgroundColorAlpha: CGFloat = 0.5
var shoulDismiss = false
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
let fadeInPresentAnimationController = MyFadeInPresentAnimationController()
fadeInPresentAnimationController.backgroundColorAlpha = backgroundColorAlpha
return fadeInPresentAnimationController
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
let fadeOutDismissAnimationController = MyFadeOutDismissAnimationController()
return fadeOutDismissAnimationController
}
}
// MARK: -
class MYFadeInPresentAnimationController: NSObject, UIViewControllerAnimatedTransitioning {
let kPresentationDuration = 0.5
var backgroundColorAlpha: CGFloat?
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return kPresentationDuration
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)!
toViewController.view.backgroundColor = UIColor.clear
let toViewFrame = transitionContext.finalFrame(for: toViewController)
let containerView = transitionContext.containerView
if let pickerContainerView = toViewController.view.viewWithTag(kContainerViewTag) {
let transform = CGAffineTransform(translationX: 0.0, y: pickerContainerView.frame.size.height)
pickerContainerView.transform = transform
}
toViewController.view.frame = toViewFrame
containerView.addSubview(toViewController.view)
UIView.animate(withDuration: 0.3, delay: 0.0, options: .curveLinear , animations: {
toViewController.view.backgroundColor = UIColor(white: 0.0, alpha: self.backgroundColorAlpha!)
if let pickerContainerView = toViewController.view.viewWithTag(kContainerViewTag) {
pickerContainerView.transform = CGAffineTransform.identity
}
}) { (finished) in
transitionContext.completeTransition(true)
}
}
}
// MARK: -
class MYFadeOutDismissAnimationController: NSObject, UIViewControllerAnimatedTransitioning {
let kDismissalDuration = 0.15
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return kDismissalDuration
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let fromViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)!
let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)!
let containerView = transitionContext.containerView
containerView.addSubview(toViewController.view)
containerView.sendSubview(toBack: toViewController.view)
UIView.animate(withDuration: kDismissalDuration, delay: 0.0, options: .curveLinear, animations: {
// fromViewController.view.backgroundColor = UIColor.clearColor()
// if let pickerContainerView = toViewController.view.viewWithTag(kContainerViewTag) {
// let transform = CGAffineTransformMakeTranslation(0.0, pickerContainerView.frame.size.height)
// pickerContainerView.transform = transform
// }
fromViewController.view.alpha = 0.0
}) { (finished) in
let canceled: Bool = transitionContext.transitionWasCancelled
transitionContext.completeTransition(true)
if !canceled {
UIApplication.shared.keyWindow?.addSubview(toViewController.view)
}
}
}
}
在呈现的 viewController 中,我正在执行以下操作
var customTransitioningDelegate: MYFadeInFadeOutTransitioning? = MYFadeInFadeOutTransitioning()
init() {
super.init(nibName: "SomeNibName", bundle: Bundle.main)
transitioningDelegate = customTransitioningDelegate
modalPresentationStyle = .custom
customTransitioningDelegate?.backgroundColorAlpha = 0.0
}
它确实显示了 viewController,我也可以看到背景 viewController。但我希望它从底部用动画呈现。并用动画解雇到底部。我该怎么做?
最佳答案
如果你想在半个屏幕上显示一个 View Controller ,我建议使用 UIPresentationController
类,它允许你在显示 View Controller 时设置它的框架。忠告,此方法将停止 presentingViewController
的用户交互,直到您关闭 presentedViewController
,因此如果您想在保留屏幕的一半以上显示 View Controller 用户与 presentingViewController
的交互你应该像建议的其他答案一样使用容器 View 。
这是一个 UIPresentationController 类的示例,它可以执行您想要的操作
import UIKit
class ForgotPasswordPresentationController: UIPresentationController{
let blurEffectView: UIVisualEffectView!
var tapGestureRecognizer: UITapGestureRecognizer = UITapGestureRecognizer()
func dismiss(){
self.presentedViewController.dismiss(animated: true, completion: nil)
}
override init(presentedViewController: UIViewController, presenting presentingViewController: UIViewController?) {
let blurEffect = UIBlurEffect(style: UIBlurEffectStyle.dark)
blurEffectView = UIVisualEffectView(effect: blurEffect)
super.init(presentedViewController: presentedViewController, presenting: presentingViewController)
tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.dismiss))
blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.blurEffectView.isUserInteractionEnabled = true
self.blurEffectView.addGestureRecognizer(tapGestureRecognizer)
}
override var frameOfPresentedViewInContainerView: CGRect{
return CGRect(origin: CGPoint(x: 0, y: self.containerView!.frame.height/2), size: CGSize(width: self.containerView!.frame.width, height: self.containerView!.frame.height/2))
}
override func dismissalTransitionWillBegin() {
self.presentedViewController.transitionCoordinator?.animate(alongsideTransition: { (UIViewControllerTransitionCoordinatorContext) in
self.blurEffectView.alpha = 0
}, completion: { (UIViewControllerTransitionCoordinatorContext) in
self.blurEffectView.removeFromSuperview()
})
}
override func presentationTransitionWillBegin() {
self.blurEffectView.alpha = 0
self.containerView?.addSubview(blurEffectView)
self.presentedViewController.transitionCoordinator?.animate(alongsideTransition: { (UIViewControllerTransitionCoordinatorContext) in
self.blurEffectView.alpha = 1
}, completion: { (UIViewControllerTransitionCoordinatorContext) in
})
}
override func containerViewWillLayoutSubviews() {
super.containerViewWillLayoutSubviews()
presentedView!.layer.masksToBounds = true
presentedView!.layer.cornerRadius = 10
}
override func containerViewDidLayoutSubviews() {
super.containerViewDidLayoutSubviews()
self.presentedView?.frame = frameOfPresentedViewInContainerView
blurEffectView.frame = containerView!.bounds
}
}
当您在 presentedViewController
框架外点击时,这还会添加模糊 View 和关闭点击。您需要设置 presentedViewController
的 transitioningDelegate
并实现
presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController?
里面有方法。不要忘记也设置
modalPresentationStyle = .custom
呈现的 ViewController
我发现使用 UIPresentationController 是一种更简洁的方法。祝你好运
关于ios - 如何在半屏上呈现 ViewController,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42106980/