2015-08-12 5 views
7

Я использую пользовательские переходы для отображения полноэкранного модального игрового представления. Когда пользователь запускает игру, контроллер корневого представления масштабируется вниз на экране, в то время как полноэкранный игровой контроллер масштабируется от большего масштаба вниз на дисплей при переходе от 0% непрозрачности до 100% непрозрачности. Просто!iOS пользовательские переходы и вращение

Переход выглядит отлично и отлично работает, а также правильно реверсирует анимацию при отключении контроллера игрового представления.

Проблема, с которой я сталкиваюсь, заключается в том, что если устройство повернуто , пока отображается полноэкранный контроллер игрового вида, при возврате к контроллеру корневого представления макет все болван. И дальнейшее вращение не устраняет проблему, макет винтовой и остается завинчивающейся.

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

Вот мой Переход делегат:

class FullscreenModalTransitionManager: NSObject, UIViewControllerAnimatedTransitioning, UIViewControllerTransitioningDelegate { 

    private var presenting:Bool = true 

    // MARK: UIViewControllerAnimatedTransitioning protocol methods 

    func animateTransition(transitionContext: UIViewControllerContextTransitioning) { 

     // get reference to our fromView, toView and the container view that we should perform the transition in 
     let container = transitionContext.containerView() 
     let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey)! 
     let toView = transitionContext.viewForKey(UITransitionContextToViewKey)! 

     let scale:CGFloat = 1.075 
     //let bigScale = CGAffineTransformMakeScale(scale, scale) 
     //let smallScale = CGAffineTransformMakeScale(1/scale,1/scale) 
     let bigScale = CATransform3DMakeScale(scale, scale, 1) 
     let smallScale = CATransform3DMakeScale(1/scale, 1/scale, 1) 
     let smallOpacity:CGFloat = 0.5 
     let presenting = self.presenting 

     if presenting { 

      // when presenting, incoming view must be on top 
      container.addSubview(fromView) 
      container.addSubview(toView) 

      toView.layer.transform = bigScale 
      toView.opaque = false 
      toView.alpha = 0 

      fromView.layer.transform = CATransform3DIdentity 
      fromView.opaque = false 
      fromView.alpha = 1 
     } else { 

      // when !presenting, outgoing view must be on top 
      container.addSubview(toView) 
      container.addSubview(fromView) 

      toView.layer.transform = smallScale 
      toView.opaque = false 
      toView.alpha = smallOpacity 

      fromView.layer.transform = CATransform3DIdentity 
      fromView.opaque = false 
      fromView.alpha = 1 
     } 


     let duration = self.transitionDuration(transitionContext) 

     UIView.animateWithDuration(duration, 
      delay: 0.0, 
      usingSpringWithDamping: 0.7, 
      initialSpringVelocity: 0, 
      options: nil, 
      animations: { 

       if presenting { 
        fromView.layer.transform = smallScale 
        fromView.alpha = smallOpacity 
       } else { 
        fromView.layer.transform = bigScale 
        fromView.alpha = 0 
       } 

      }, 
      completion: nil) 

     UIView.animateWithDuration(duration, 
      delay: duration/6, 
      usingSpringWithDamping: 0.7, 
      initialSpringVelocity: 0.5, 
      options: nil, 
      animations: { 
       toView.layer.transform = CATransform3DIdentity 
       toView.alpha = 1 
      }, 
      completion: { finished in 
       transitionContext.completeTransition(true) 
      }) 
    } 

    func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval { 
     return 0.5 
    } 

    // MARK: UIViewControllerTransitioningDelegate protocol methods 

    func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? { 
     self.presenting = true 
     return self 
    } 

    func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { 
     self.presenting = false 
     return self 
    } 
} 

И, для визуального, вот что мой корень-контроллер обычно выглядит следующим образом:

Correct layout for my root view controller

И, для визуального, вот что мой контроллер корневого представления выглядит, если я поворачиваю свое устройство (хотя бы один раз) в режиме игры и возвращаюсь к контроллеру корневого представления.

Broken layout, after rotating device while in fullscreen game view and returning to root view

И последнее замечание - только в случае, если он звонит любой колокол - Я использую autolayout и размера классы выложить мой взгляд корневого контроллер.

Спасибо,

ответ

4

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

Исправление, в моем переходном делетете должно было пройти транзитное представление, а в полном обратном вызове анимации было установлено его преобразование в идентичность (поскольку этот вид невидим в конце анимации и за новым видом, это не имеет никакого влияния на внешний вид)

UIView.animateWithDuration(duration, 
    delay: 0.0, 
    usingSpringWithDamping: 0.7, 
    initialSpringVelocity: 0, 
    options: nil, 
    animations: { 

     if presenting { 
      fromView.transform = smallScale 
      fromView.alpha = smallOpacity 
     } else { 
      fromView.transform = bigScale 
      fromView.alpha = 0 
     } 

    }, 
    completion: { completed in 
     // set transform of now hidden view to identity to prevent breakage during rotation 
     fromView.transform = CGAffineTransformIdentity 
    }) 
+0

Это работает только если fromVC не видны после перехода. См. Мой ответ. – daleijn

+0

Используйте и это, и ответ @agilityvision работал для меня! Когда переход завершен, вам нужно сбросить 'transform' на идентификатор, затем, когда переход начинается, вам нужно установить frame в finalFrame, а затем применить преобразование. – kientux

25

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


Проблема

enter image description here


Решение

Objective C

- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext { 

    // ViewController Reference 
    UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; 

    // Fix layout bug in iOS 9+ 
    toViewController.view.frame = [transitionContext finalFrameForViewController:toViewController]; 

    // The rest of your code ... 
} 

Swift 3,0

func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { 

    // ViewController reference 
    let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)! 

    // Fix layout bug in iOS 9+ 
    toViewController.view.frame = transitionContext.finalFrame(for: toViewController) 

    // The rest of your code ... 
} 
+0

Я получал ту же проблему на iOS 10.0, и это исправлено. Благодарю. –

1

Наконец я нашел решение этой проблемы. Вам нужно улучшить код @agilityvision. Вам нужно добавить значение BOOL, что-то вроде closeVCNow, что означает, что вы хотите, чтобы закрыть VC, и в animateTransition:, в анимации блока сделать:

if (self.closeVCNow) { 
     toVC.view.transform = CGAffineTransformIdentity; 
     toVC.view.frame = [transitionContext finalFrameForViewController:toVC]; 
     self.closeVCNow = NO; 
    }