【发布时间】:2016-10-06 14:58:45
【问题描述】:
我一生都无法理解为什么这不起作用。
有两个 VC:A 和 B。
我想在 VC A 上向右滑动以显示 VC B,但希望使其具有交互性,以便用户可以在两个 VC 之间拖动(例如在 Instagram 主屏幕上,当您左右滑动以转到相机和消息时) .目前,它没有“拖动”。您可以在 VC A 上滑动,它会转到 VC B。
这是我向右滑动的动画对象:
class SlideRightTransitionAnimator: NSObject {
let duration = 0.5
var isPresenting = false
let customInteractiveTransition = CustomInteractiveTransition()
}
// MARK: UIViewControllerTransitioningDelegate
extension SlideRightTransitionAnimator: UIViewControllerTransitioningDelegate {
// Return the animator when presenting a VC
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
isPresenting = true
return self
}
// Return the animator used when dismissing from a VC
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
isPresenting = false
return self
}
// Add the interactive transition for Presentation only
func interactionControllerForPresentation(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
return customInteractiveTransition.transitionInProgress ? customInteractiveTransition : nil
}
}
// MARK: UIViewControllerTransitioningDelegate
extension SlideRightTransitionAnimator: UIViewControllerAnimatedTransitioning {
// Return how many seconds the transiton animation will take
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return duration
}
// Animate a change from one VC to another
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
// Get reference to our fromView, toView and the container view that we should perform the transition
let container = transitionContext.containerView
let fromView = transitionContext.view(forKey: UITransitionContextViewKey.from)!
let toView = transitionContext.view(forKey: UITransitionContextViewKey.to)!
// Set up the transform we'll use in the animation
let offScreenRight = CGAffineTransform(translationX: container.frame.width, y: 0)
let offScreenLeft = CGAffineTransform(translationX: -container.frame.width, y: 0)
// Start the toView to the right of the screen
if isPresenting {
toView.transform = offScreenLeft
}
// Add the both views to our VC
container.addSubview(toView)
container.addSubview(fromView)
// Perform the animation
UIView.animate(withDuration: duration, delay: 0.0, usingSpringWithDamping: 1.0, initialSpringVelocity: 1.0, options: [], animations: {
if self.isPresenting {
fromView.transform = offScreenRight
toView.transform = CGAffineTransform.identity
}
else {
fromView.transform = offScreenLeft
toView.transform = CGAffineTransform.identity
}
}, completion: { finished in
// Tell our transitionContext object that we've finished animating
transitionContext.completeTransition(true)
})
}
}
这是我的交互式过渡控制器
class CustomInteractiveTransition: UIPercentDrivenInteractiveTransition {
weak var viewController : UIViewController!
var shouldCompleteTransition = false
var transitionInProgress = false
var completionSeed: CGFloat {
return 1 - percentComplete
}
func attachToViewController(viewController: UIViewController) {
self.viewController = viewController
setupPanGestureRecognizer(view: viewController.view)
}
private func setupPanGestureRecognizer(view: UIView) {
view.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture)))
}
func handlePanGesture(gestureRecognizer: UIPanGestureRecognizer) {
let viewTranslation = gestureRecognizer.translation(in: gestureRecognizer.view!.superview!)
var progress = (viewTranslation.x / 200)
progress = CGFloat(fminf(fmaxf(Float(progress), 0.0), 1.0))
switch gestureRecognizer.state {
case .began:
transitionInProgress = true
viewController.dismiss(animated: true, completion: nil)
case .changed:
shouldCompleteTransition = progress > 0.5
update(progress)
case .cancelled, .ended:
transitionInProgress = false
if !shouldCompleteTransition || gestureRecognizer.state == .cancelled {
cancel()
} else {
finish()
}
default:
print("Swift switch must be exhaustive, thus the default")
}
}
}
最后是 VC A 的代码:
class ViewControllerA: UITableViewController {
let slideRightTransition = SlideRightTransitionAnimator()
let customInteractiveTransition = CustomInteractiveTransition()
override func viewDidLoad() {
super.viewDidLoad()
// Add a Pan Gesture to swipe to other VC
let swipeGestureRight = UISwipeGestureRecognizer(target: self, action: #selector(swipeGestureRightAction))
swipeGestureRight.direction = .right
view.addGestureRecognizer(swipeGestureRight)
}
// MARK: Pan gestures
func swipeGestureRightAction() {
performSegue(withIdentifier: "showMapSegue", sender: self)
}
// MARK: Prepare for segue
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showVCB" {
// This gets a reference to the screen that we're about to transition to and from
let toViewController = segue.destination as UIViewController
// Instead of using the default transition animation, we'll ask the segue to use our custom SlideRightTransitionAnimator object to manage the transition animation
toViewController.transitioningDelegate = slideRightTransition
// Add the Interactive gesture transition to the VC
customInteractiveTransition.attachToViewController(viewController: toViewController)
}
}
提前谢谢你!!!
【问题讨论】:
标签: ios swift animation transition interactive