2017-02-08 112 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

相關問題