2017-02-08 4 views
3

У меня есть UIViewController, которые имеют только UIView, который покрывает 1/3 of viewController снизу. Как этоКак представить ViewController на полуэкранном

enter image description here

Я хочу представить эту ViewController на другой ViewController. Он должен появиться с нижнего анимированного, и он должен отклоняться на дне анимированным.

Но я не хочу, чтобы он охватывал весь экран. ViewController, на котором он представлен, должен быть виден сзади.

Похоже, что основной вопрос, но я не могу это сделать. Может ли кто-нибудь указать мне направление?

Edit:

Это то, что я пытался до сих пор. Я создал эти классы

// 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

Я бы рекомендовал реализовать эту функцию с помощью Container Views. Посмотрите here для справки.

Это означает, что вы можете показать UIViewController (и его подклассы), встроенные в UIView, в другой ViewController. Затем вы можете анимировать затухание или что угодно.

+0

Точно Umair вы должны использовать концепцию контейнера здесь. –

0

Вы также можете добиться эффекта, представив контроллер вида по модулю и установив свойство стиля представления в полноэкранное, свойство стиля перехода, чтобы покрыть вертикальное положение и установить альфа-компонент фонового цвета вида на 0,1.

2

Для этого вы можете использовать UIPresentationController. Реализовать метод UIViewControllerTransitioningDelegate на представлении ViewController и вернуть PresentationController от метода делегата

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

Вы можете передать этот answer, который имеет аналогичное требование. В качестве альтернативы вы можете использовать анимацию UIView или встроенный контроллер просмотра, как это предлагается в других ответах.

Edit:

образец проекта найден в 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 кадра. Вы должны установить transitioningDelegate в presentedViewController и реализовать метод

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

там. Не забудьте также установить modalPresentationStyle = .custom из presentedViewController

Я найти применение в 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 варианты, установите свои ограничения на (вверху: -, Bottom: 0, Ведущий: 0, Скользящий: 0), Установите это высоту ограничение на равной высоту с надтаблицей (самообеспечение .Просмотреть) и изменить его multipler на 0.33 или 0.34. Надеюсь, что это поможет. Экран короткий. enter image description here

0

Вы можете использовать Present Modally раскадровки SEGUE с презентацией, установленной в Over Full Screen и установив представленный контроллера представления backgroundColor очистить.

Present modally

Смежные вопросы