如果您尝试进行这种拆分转换,我已经为视图控制器转换创建了一个动画控制器。如果你看代码,你会发现可以有两种不同的过渡方式,从中间打开 from view 或者 toview 来并折叠在 from view 的顶部。
这是下面代码如何工作的小 gif;
class AnimationController: NSObject, UIViewControllerAnimatedTransitioning {
let presenting: Bool
init(presenting: Bool) {
self.presenting = presenting
}
func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval {
return 1.0
}
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
animateOutImagesWithContext(transitionContext)
//animateInImagesWithContext(transitionContext)
}
func snapshotView(view: UIView!) -> UIImage {
UIGraphicsBeginImageContext(view.bounds.size)
view.drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true)
let snapshotImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return snapshotImage
}
func animateOutImagesWithContext(transitionContext:UIViewControllerContextTransitioning) {
let containerView = transitionContext.containerView()
let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)
let toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)
let fromView = fromViewController!.view
let toView = toViewController!.view
containerView.addSubview(toView)
let snapshotImage = snapshotView(fromView)
fromView.removeFromSuperview()
let imageViews = animatingOutImageViews(snapshotImage)
containerView.addSubview(imageViews.firstImageView)
containerView.addSubview(imageViews.secondImageView)
UIView.animateWithDuration(transitionDuration(transitionContext), animations: { () -> Void in
let firstImageView = imageViews.firstImageView
let secondImageView = imageViews.secondImageView
if self.presenting {
firstImageView.frame = CGRectOffset(firstImageView.frame, -CGRectGetWidth(firstImageView.frame), 0)
secondImageView.frame = CGRectOffset(secondImageView.frame, CGRectGetWidth(secondImageView.frame), 0)
} else {
firstImageView.frame = CGRectOffset(firstImageView.frame, 0, -CGRectGetHeight(firstImageView.frame))
secondImageView.frame = CGRectOffset(secondImageView.frame, 0, CGRectGetHeight(secondImageView.frame))
}
}) { (completed: Bool) -> Void in
imageViews.firstImageView.removeFromSuperview()
imageViews.secondImageView.removeFromSuperview()
transitionContext.completeTransition(true)
}
}
func animateInImagesWithContext(transitionContext:UIViewControllerContextTransitioning) {
let containerView = transitionContext.containerView()
let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)
let toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)
let fromView = fromViewController!.view
let toView = toViewController!.view
containerView.insertSubview(toView, belowSubview: fromView)
let snapshotImage = snapshotView(toView)
let imageViews = animatingInImageViews(snapshotImage)
containerView.addSubview(imageViews.firstImageView)
containerView.addSubview(imageViews.secondImageView)
UIView.animateWithDuration(transitionDuration(transitionContext), animations: { () -> Void in
let firstImageView = imageViews.firstImageView
let secondImageView = imageViews.secondImageView
if self.presenting {
firstImageView.frame = CGRectOffset(firstImageView.frame, 0, CGRectGetHeight(firstImageView.frame))
secondImageView.frame = CGRectOffset(secondImageView.frame, 0, -CGRectGetHeight(secondImageView.frame))
} else {
firstImageView.frame = CGRectOffset(firstImageView.frame, CGRectGetWidth(firstImageView.frame), 0)
secondImageView.frame = CGRectOffset(secondImageView.frame, -CGRectGetWidth(secondImageView.frame),0)
}
}) { (completed: Bool) -> Void in
fromView.removeFromSuperview()
imageViews.firstImageView.removeFromSuperview()
imageViews.secondImageView.removeFromSuperview()
transitionContext.completeTransition(true)
}
}
func animatingOutImageViews(snapshotImage: UIImage) -> (firstImageView: UIImageView!, secondImageView: UIImageView!)
{
let imageSize = snapshotImage.size
var firstPartFrame: CGRect
var secondPartFrame: CGRect
if presenting {
firstPartFrame = CGRectMake(0, 0, imageSize.width * 0.5, imageSize.height)
secondPartFrame = CGRectOffset(firstPartFrame, CGRectGetWidth(firstPartFrame), 0)
} else {
firstPartFrame = CGRectMake(0, 0, imageSize.width, imageSize.height * 0.5)
secondPartFrame = CGRectOffset(firstPartFrame, 0, CGRectGetHeight(firstPartFrame))
}
let firstImage = getImage(snapshotImage, insideRect: firstPartFrame)
let secondImage = getImage(snapshotImage, insideRect: secondPartFrame)
let firstImageView = UIImageView(frame: firstPartFrame)
firstImageView.image = firstImage
let secondImageView = UIImageView(frame: secondPartFrame)
secondImageView.image = secondImage
return (firstImageView, secondImageView)
}
func animatingInImageViews(snapshotImage: UIImage) -> (firstImageView: UIImageView!, secondImageView: UIImageView!)
{
let imageSize = snapshotImage.size
var firstPartFrame: CGRect
var secondPartFrame: CGRect
if presenting {
firstPartFrame = CGRectMake(0, 0, imageSize.width, imageSize.height * 0.5)
secondPartFrame = CGRectOffset(firstPartFrame, 0, CGRectGetHeight(firstPartFrame))
} else {
firstPartFrame = CGRectMake(0, 0, imageSize.width * 0.5, imageSize.height)
secondPartFrame = CGRectOffset(firstPartFrame, CGRectGetWidth(firstPartFrame), 0)
}
let firstImage = getImage(snapshotImage, insideRect: firstPartFrame)
let secondImage = getImage(snapshotImage, insideRect: secondPartFrame)
let firstImageView = UIImageView(image: firstImage)
let secondImageView = UIImageView(image: secondImage)
if presenting {
firstImageView.frame = CGRectOffset(firstPartFrame, 0, -CGRectGetHeight(firstPartFrame))
secondImageView.frame = CGRectOffset(secondPartFrame, 0, CGRectGetHeight(secondPartFrame))
} else {
firstImageView.frame = CGRectOffset(firstPartFrame, -CGRectGetWidth(firstPartFrame), 0)
secondImageView.frame = CGRectOffset(secondPartFrame, CGRectGetWidth(secondPartFrame), 0)
}
return (firstImageView, secondImageView)
}
func getImage(image: UIImage, insideRect rect:CGRect) -> UIImage {
let image = CGImageCreateWithImageInRect(image.CGImage, rect)!
return UIImage(CGImage: image)!
}
}
class SecondViewController: UIViewController, UIViewControllerTransitioningDelegate {
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
init() {
super.init(nibName: nil, bundle: nil)
self.transitioningDelegate = self
}
override func viewDidLoad() {
super.viewDidLoad()
let view1 = UIView(frame: CGRectZero)
view1.backgroundColor = UIColor.purpleColor()
view1.setTranslatesAutoresizingMaskIntoConstraints(false)
let view2 = UIView(frame: CGRectZero)
view2.backgroundColor = UIColor.cyanColor()
view2.setTranslatesAutoresizingMaskIntoConstraints(false)
view.addSubview(view1)
view.addSubview(view2)
let views = [
"view1": view1,
"view2": view2
]
let vFormat = "V:|[view1][view2(==view1)]|"
let hFormat = "H:|[view1]|"
let hConstraints = NSLayoutConstraint.constraintsWithVisualFormat(hFormat,
options: .allZeros,
metrics: nil,
views: views)
let vConstraints = NSLayoutConstraint.constraintsWithVisualFormat(vFormat,
options: .AlignAllLeft | .AlignAllRight,
metrics: nil,
views: views)
view.addConstraints(hConstraints)
view.addConstraints(vConstraints)
let tapGestureRecognizer = UITapGestureRecognizer(target: self,
action: "tapped")
view.addGestureRecognizer(tapGestureRecognizer)
}
func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return AnimationController(presenting: true)
}
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return AnimationController(presenting: false)
}
func tapped() {
let nextViewController = NextViewController()
dismissViewControllerAnimated(true, completion: nil)
}
}
class FirstViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let view1 = UIView(frame: CGRectZero)
view1.backgroundColor = UIColor.redColor()
view1.setTranslatesAutoresizingMaskIntoConstraints(false)
let view2 = UIView(frame: CGRectZero)
view2.backgroundColor = UIColor.greenColor()
view2.setTranslatesAutoresizingMaskIntoConstraints(false)
view.addSubview(view1)
view.addSubview(view2)
let views = [
"view1": view1,
"view2": view2
]
let hFormat = "H:|[view1][view2(==view1)]|"
let vFormat = "V:|[view1]|"
let hConstraints = NSLayoutConstraint.constraintsWithVisualFormat(hFormat,
options: .AlignAllTop | .AlignAllBottom,
metrics: nil,
views: views)
let vConstraints = NSLayoutConstraint.constraintsWithVisualFormat(vFormat,
options: .allZeros,
metrics: nil,
views: views)
view.addConstraints(hConstraints)
view.addConstraints(vConstraints)
let tapGestureRecognizer = UITapGestureRecognizer(target: self,
action: "tapped")
view.addGestureRecognizer(tapGestureRecognizer)
}
func tapped() {
let secondViewController = SecondViewController()
presentViewController(secondViewController, animated: true, completion: nil)
}
}
代码可能稍长,但必须易于理解。如果你愿意,可以稍微调整一下。