我正在尝试像在Snapchat中一样进行过渡动画。当用户向下切换屏幕时,视频会继续顺畅播放。
容器中的图像执行转换时
我正在添加FromViewController视图作为转换容器子视图。 (FromViewController使用AVPlayerLayer播放视频)
但是在容器层(我添加了FromViewController)的视频转换滞后时,它无法顺利播放。
containerView!.addSubview((fromVC?.view)!)
我发布以下代码。
class CircleTransitionAnimator: NSObject , UIViewControllerAnimatedTransitioning
{
weak var transitionContext: UIViewControllerContextTransitioning?
func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return 0.5;
}
@IBAction func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
self.transitionContext = transitionContext
let containerView = transitionContext.containerView()
let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) //as! ViewController
let toVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) //as! ViewController
containerView!.addSubview((fromVC?.view)!)
let initialFrame = CGRectMake(-fromVC!.view.frame.size.width/2,0, fromVC!.view.frame.size.height, fromVC!.view.frame.size.height ) as CGRect
var endFrame : CGRect = CGRectMake(0, 0, 0, 0)
if toVC?.isKindOfClass(ViewController) == true {
let viewToMove = toVC as! ViewController
let cellForDismiss = viewToMove.cellViewToDismissTo
if cellForDismiss != nil {
endFrame = cellForDismiss.frame as CGRect
}
self.transitionContext?.initialFrameForViewController(fromVC!)
let maskPath = UIBezierPath(rect: initialFrame)
let maskLayer = CAShapeLayer()
maskLayer.frame = toVC!.view.frame;
maskLayer.path = maskPath.CGPath;
let smallCirclePath = UIBezierPath(rect: endFrame)
maskLayer.path = smallCirclePath.CGPath;
fromVC!.view.layer.mask = maskLayer
let pathAnimation = CABasicAnimation(keyPath: "path")
pathAnimation.fromValue = maskPath.CGPath
pathAnimation.toValue = smallCirclePath
pathAnimation.duration = self.transitionDuration(transitionContext)
let opacityAnimation = CABasicAnimation(keyPath: "opacity")
opacityAnimation.fromValue = 1.0;
opacityAnimation.toValue = 0.5;
opacityAnimation.duration = self.transitionDuration(transitionContext)
CATransaction.begin()
CATransaction.setCompletionBlock({
transitionContext.completeTransition(transitionContext.transitionWasCancelled())
toVC!.view.layer.mask = nil
fromVC!.view.layer.mask = nil
sourceSnap.removeFromSuperview()
})
maskLayer.addAnimation(pathAnimation, forKey: "pathAnimation")
maskLayer.addAnimation(opacityAnimation, forKey: "opacityAnimation")
CATransaction.commit()
}
else{
if fromVC?.isKindOfClass(ViewController) == true {
let viewToMove = fromVC as! ViewController
let cellForDismiss = viewToMove.cellViewToDismissTo
containerView!.addSubview(toVC!.view)
let circleMaskPathInitial = UIBezierPath(rect: cellForDismiss!.frame)
let extremePoint = CGPoint(x: cellForDismiss!.center.x - 0, y: cellForDismiss!.center.y - CGRectGetHeight(toVC!.view.bounds))
let radius = sqrt((extremePoint.x*extremePoint.x) + (extremePoint.y*extremePoint.y))
let circleMaskPathFinal = UIBezierPath(rect: CGRectInset(cellForDismiss!.frame, -radius, -radius))
let maskLayer = CAShapeLayer()
maskLayer.path = circleMaskPathFinal.CGPath
toVC!.view.layer.mask = maskLayer
let maskLayerAnimation = CABasicAnimation(keyPath: "path")
maskLayerAnimation.fromValue = circleMaskPathInitial.CGPath
maskLayerAnimation.toValue = circleMaskPathFinal.CGPath
maskLayerAnimation.duration = self.transitionDuration(transitionContext)
maskLayerAnimation.delegate = self
maskLayer.addAnimation(maskLayerAnimation, forKey: "path")
}
}
}
override func animationDidStop(anim: CAAnimation, finished flag: Bool) {
self.transitionContext?.completeTransition(!self.transitionContext!.transitionWasCancelled())
self.transitionContext?.viewControllerForKey(UITransitionContextFromViewControllerKey)?.view.layer.mask = nil
}
}
在另一个班级,我正在处理平移手势状态。
class NavigationControllerDelegate: NSObject , UINavigationControllerDelegate {
@IBOutlet weak var navigationController: UINavigationController?
var interactionController: UIPercentDrivenInteractiveTransition?
var transitionInProgress : Bool = false
var shouldCompleteTransition : Bool = false
var parentViewController : UIViewController!
var percent : CGFloat!
override func awakeFromNib() {
super.awakeFromNib()
// Added Pan gesture to Navigatin Controller
let panGesture = UIPanGestureRecognizer(target: self, action: Selector("panned:"))
self.navigationController!.view.addGestureRecognizer(panGesture)
let controller :[UIViewController] = (self.navigationController?.viewControllers)!
for contro in controller {
if contro.isKindOfClass(ViewController) == true {
parentViewController = contro
}
}
}
@IBAction func panned(gestureRecognizer: UIPanGestureRecognizer) {
let point : CGPoint = gestureRecognizer .translationInView(self.parentViewController.view)
self.percent = CGFloat( fmaxf(fminf(Float(point.y) / 400.0 , 0.99), 0.0))
let velocity : CGPoint = gestureRecognizer.velocityInView(self.parentViewController.view)
// Percent is used for completing transaction , its value tells when the complete transition should start ( after the point when we stop sliding the view down )
switch gestureRecognizer.state {
case .Began:
//
self.transitionInProgress = true;
self.interactionController = UIPercentDrivenInteractiveTransition()
self.navigationController?.popViewControllerAnimated(true)
case .Changed:
// when we use swipe down then this block is continously called and update the interactve transition
self.shouldCompleteTransition = (Double(self.percent) > 0.0 );
let translation = gestureRecognizer.translationInView(self.navigationController!.view)
let completionProgress = translation.x/CGRectGetWidth(self.navigationController!.view.bounds)
self.interactionController?.updateInteractiveTransition(self.percent)
case .Ended:
// When swipe gesture ends , we finish the transition or in any other case "cancel" the transition
self.transitionInProgress = false;
if (self.shouldCompleteTransition == false || gestureRecognizer.state == .Cancelled) {
self.interactionController?.finishInteractiveTransition()
}else{
self.interactionController?.cancelInteractiveTransition()
}
self.interactionController = nil
default:
self.interactionController?.cancelInteractiveTransition()
self.interactionController = nil
}
}
func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return CircleTransitionAnimator()
}
func navigationController(navigationController: UINavigationController, interactionControllerForAnimationController animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
return self.interactionController
}
}