2017-02-08 66 views
3

我有一个UIViewController,它只有一个UIView,它覆盖底部1/3的viewController。像这样如何在半屏上显示ViewController

enter image description here

我想提出上其他的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为好。但我希望它能从动画的底部呈现。并用动画关闭底部。我怎样才能做到这一点 ?

+0

可以显示乌尔试图代码 –

+0

您可以添加视图控制器为孩子 –

+0

@ Anbu.Karthik请立即检查。 –

回答

5

我建议通过使用容器视图来实现此功能。看看here作为参考。

这意味着您可以在另一个ViewController中显示嵌入UIView中的UIViewController(以及它的子类)。然后你可以使淡入或任何你想要的动画动画。

+0

准确地说,Umair你必须在这里使用容器视图的概念。 –

0

您还可以通过以模态方式呈现视图控制器并将呈现样式属性设置为覆盖全屏,将过渡样式属性设置为覆盖垂直并将视图的背景颜色的alpha分量设置为0.1来实现该效果。

2

您可以使用UIPresentationController来实现此目的。实施上呈现的ViewController的UIViewControllerTransitioningDelegate方法,并从委托方法返回的PresentationController

func presentationController(forPresented presented: UIViewController, 
          presenting: UIViewController?, 
           source: UIViewController) -> UIPresentationController? 

你可以参考这个answer它有类似的要求。或者,您可以按照其他答案中的建议使用UIView动画或嵌入式视图控制器。

编辑:在Github上

https://github.com/martinnormark/HalfModalPresentationController

8

发现如果你想超过一半的屏幕呈现一个视图控制器我建议使用UIPresentationController类它将允许你设定框架

示例项目视图控制器在呈现时的状态。一个忠告,这种方法将停止presentingViewController的用户交互,直到你关闭presentedViewController,所以如果你想在保持用户与presentingViewController交互的同时显示视图控制器超过一半的屏幕,你应该使用像其他答案一样的容器视图建议。 这是一个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框架外解雇。您需要设置presentedViewControllertransitioningDelegate,并在那里执行

presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController?

方法。不要忘了也设置 modalPresentationStyle = .custom presentsViewController

我觉得UIPresentationController的用法是一个更干净的方法。祝你好运

+0

这是一个很好的答案。我应该如何调整它,当呈现的视图控制器已经有一个'UIPopoverPresentationController',但在iPhone上,我希望呈现的视图控制器只显示在屏幕的一半。 – Jan

1

有更新的代码来实现此功能。在动作要呈现的ViewController

@IBAction func btnShow(_ sender: Any) { 
     let storyboard = UIStoryboard(name: "Main", bundle: nil) 
     let pvc = storyboard.instantiateViewController(withIdentifier: "SubViewController") as! SubViewController 
     pvc.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext 

     self.present(pvc, animated: true, completion: nil) 
    } 

转到情节提要选择subViewController在里面添加UIViews模糊效果其限制设置为(顶:0,底部:0,领先: 0,Trailing:0)适用于所有方面,并将其颜色更改为黑色并将其设置为alpha。而在这之后的选项添加其他UIViews,将其约束到(上: - ,底部:0,领先:0,尾随:0),设置它的高度约束相等的高度与上海华(个体经营。查看)并将它的倍数更改为0.33或0.34。 希望它有帮助。 屏幕短。 enter image description here

0

您可以使用Present Modally故事版segue,并将演示文稿设置为Over Full Screen,并将所呈现的视图控制器的backgroundColor设置为清除。

Present modally

相关问题