变更记录
序号 | 录入时间 | 录入人 | 备注 |
---|---|---|---|
1 | 2015-03-03 | Alfred Jiang | - |
2 | 2015-12-22 | Alfred Jiang | - |
方案名称
动画 - 页面跳转 - 自定义模态跳转动画
关键字
动画 \ 跳转 \ UINavigationController \ UINavigationControllerDelegate \ UIViewControllerAnimatedTransitioning
需求场景
- 对页面跳转动画有特殊需求时
参考链接
详细内容
UINavigationController
- Swift 解决方案
定义 NavigationControllerDelegate.swift
//
// NavigationControllerDelegate.swift
// CircleTransition
//
// Created by Rounak Jain on 23/10/14.
// Copyright (c) 2014 Rounak Jain. All rights reserved.
//
import UIKit
class NavigationControllerDelegate: NSObject, UINavigationControllerDelegate {
var startPoint : CGPoint?
weak var navigationController: UINavigationController?
var interactionController: UIPercentDrivenInteractiveTransition?
override func awakeFromNib() {
super.awakeFromNib()
var panGesture = UIPanGestureRecognizer(target: self, action: Selector("panned:"))
self.navigationController!.view.addGestureRecognizer(panGesture)
}
func panned(gestureRecognizer: UIPanGestureRecognizer) {
switch gestureRecognizer.state {
case .Began:
startPoint = gestureRecognizer.locationInView(self.navigationController?.view)
if startPoint!.x < 20
{
self.interactionController = UIPercentDrivenInteractiveTransition()
if self.navigationController?.viewControllers.count > 1 {
GJViewTools.CLICK_POINT = gestureRecognizer.locationInView(self.navigationController?.view)
GJViewTools.DRAG_POINT = true
self.navigationController?.popViewControllerAnimated(true)
}
}
case .Changed:
if startPoint!.x < 20
{
var translation = gestureRecognizer.translationInView(self.navigationController!.view)
var completionProgress = translation.x/CGRectGetWidth(self.navigationController!.view.bounds)
self.interactionController?.updateInteractiveTransition(completionProgress)
}
case .Ended:
if startPoint!.x < 20
{
if (gestureRecognizer.velocityInView(self.navigationController!.view).x > 0) {
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? {
var cirAnimator : CircleTransitionAnimator = CircleTransitionAnimator()
cirAnimator.navigationOperation = operation
return cirAnimator
}
func navigationController(navigationController: UINavigationController, interactionControllerForAnimationController animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
return self.interactionController
}
}
CircleTransitionAnimator.swift
//
// CircleTransitionAnimator.swift
// CircleTransition
//
// Created by Rounak Jain on 23/10/14.
// Copyright (c) 2014 Rounak Jain. All rights reserved.
//
import UIKit
class CircleTransitionAnimator: NSObject, UIViewControllerAnimatedTransitioning {
weak var transitionContext: UIViewControllerContextTransitioning?
var navigationOperation: UINavigationControllerOperation?
func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval {
return GJViewTools.DURATION_TIME;
}
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
self.transitionContext = transitionContext
var containerView = transitionContext.containerView()
var fromViewController : UIViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!
var toViewController : UIViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!
var button = UIButton(frame: CGRectMake(0, 0, 10, 10))
button.center = GJViewTools.CLICK_POINT
if navigationOperation == UINavigationControllerOperation.Pop && !GJViewTools.DRAG_POINT {
var snapshotImageView: UIView = fromViewController.view.snapshotViewAfterScreenUpdates(false)
toViewController.view.addSubview(snapshotImageView)
containerView.addSubview(toViewController.view)
var circleMaskPathInitial = UIBezierPath(ovalInRect: button.frame)
var radius = sqrt((SCREEN_HEIGH*SCREEN_HEIGH) + (SCREEN_WIDTH*SCREEN_WIDTH))
var circleMaskPathFinal = UIBezierPath(ovalInRect: CGRectInset(button.frame, -radius, -radius))
var maskLayer = CAShapeLayer()
maskLayer.path = circleMaskPathFinal.CGPath
snapshotImageView.layer.mask = maskLayer
var maskLayerAnimation = CABasicAnimation(keyPath: "path")
maskLayerAnimation.fromValue = circleMaskPathFinal.CGPath
maskLayerAnimation.toValue = circleMaskPathInitial.CGPath
maskLayerAnimation.duration = self.transitionDuration(transitionContext)
maskLayerAnimation.delegate = self
maskLayer.addAnimation(maskLayerAnimation, forKey: "path")
self.delay(self.transitionDuration(transitionContext) - 0.1, closure: { () -> () in
snapshotImageView.removeFromSuperview()
})
}
else
{
containerView.addSubview(toViewController.view)
var circleMaskPathInitial = UIBezierPath(ovalInRect: button.frame)
var radius = sqrt((SCREEN_HEIGH*SCREEN_HEIGH) + (SCREEN_WIDTH*SCREEN_WIDTH))
var circleMaskPathFinal = UIBezierPath(ovalInRect: CGRectInset(button.frame, -radius, -radius))
var maskLayer = CAShapeLayer()
maskLayer.path = circleMaskPathFinal.CGPath
toViewController.view.layer.mask = maskLayer
var 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
}
}
使用
var navDelegate : NavigationControllerDelegate = NavigationControllerDelegate()
navDelegate.navigationController = frontNav
frontNav.delegate = navDelegate
navDelegate.awakeFromNib()
ModelTransition
- Swift 解决方案
定义 ModelTransitionDelegate.swift
//
// ModelTransitionDelegate.swift
// GrandJustice
//
// Created by Alfred Jiang on 2/6/15.
// Copyright (c) 2015 FYH. All rights reserved.
//
import UIKit
enum ModalPresentingType {
case Present, Dismiss
}
class ModelTransitionDelegate: NSObject,UIViewControllerTransitioningDelegate {
func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
var modelAnimator : ModelTransitionAnimator = ModelTransitionAnimator()
modelAnimator.modalPresentingType = ModalPresentingType.Present
return modelAnimator
}
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
var modelAnimator : ModelTransitionAnimator = ModelTransitionAnimator()
modelAnimator.modalPresentingType = ModalPresentingType.Dismiss
return modelAnimator
}
}
ModelTransitionAnimator.swift
//
// ModelTransitionAnimator.swift
// GrandJustice
//
// Created by Alfred Jiang on 2/6/15.
// Copyright (c) 2015 FYH. All rights reserved.
//
import UIKit
class ModelTransitionAnimator: NSObject,UIViewControllerAnimatedTransitioning {
var modalPresentingType: ModalPresentingType?
weak var transitionContext: UIViewControllerContextTransitioning?
func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval {
return 0.6
}
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
self.transitionContext = transitionContext
var containerView = transitionContext.containerView()
var fromViewController : UIViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!
var toViewController : UIViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!
var button = UIButton(frame: CGRectMake(0, 0, 10, 10))
button.center = GJViewTools.CLICK_POINT
if modalPresentingType == ModalPresentingType.Dismiss {
var snapshotImageView: UIView = fromViewController.view.snapshotViewAfterScreenUpdates(false)
toViewController.view.addSubview(snapshotImageView)
containerView.addSubview(toViewController.view)
var circleMaskPathInitial = UIBezierPath(ovalInRect: button.frame)
var radius = sqrt((SCREEN_HEIGH*SCREEN_HEIGH) + (SCREEN_WIDTH*SCREEN_WIDTH))
var circleMaskPathFinal = UIBezierPath(ovalInRect: CGRectInset(button.frame, -radius, -radius))
var maskLayer = CAShapeLayer()
maskLayer.path = circleMaskPathFinal.CGPath
snapshotImageView.layer.mask = maskLayer
var maskLayerAnimation = CABasicAnimation(keyPath: "path")
maskLayerAnimation.fromValue = circleMaskPathFinal.CGPath
maskLayerAnimation.toValue = circleMaskPathInitial.CGPath
maskLayerAnimation.duration = self.transitionDuration(transitionContext)
maskLayerAnimation.delegate = self
maskLayer.addAnimation(maskLayerAnimation, forKey: "path")
self.delay(self.transitionDuration(transitionContext) - 0.1, closure: { () -> () in
snapshotImageView.removeFromSuperview()
})
}
else
{
containerView.addSubview(toViewController.view)
var circleMaskPathInitial = UIBezierPath(ovalInRect: button.frame)
var radius = sqrt((SCREEN_HEIGH*SCREEN_HEIGH) + (SCREEN_WIDTH*SCREEN_WIDTH))
var circleMaskPathFinal = UIBezierPath(ovalInRect: CGRectInset(button.frame, -radius, -radius))
var maskLayer = CAShapeLayer()
maskLayer.path = circleMaskPathFinal.CGPath
toViewController.view.layer.mask = maskLayer
var 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
}
}
使用
var transDelegate : ModelTransitionDelegate = ModelTransitionDelegate()
var helpNav = UINavigationController(rootViewController: tipsVC)
helpNav.transitioningDelegate = self.transDelegate
self.presentViewController(helpNav, animated: true, completion: { () -> Void in
})
效果图
(无)
备注
(无)