【问题标题】:UIView split transitionUIView 分割过渡
【发布时间】:2015-05-26 14:58:44
【问题描述】:

很有可能我只是使用了错误的术语,但我一直在寻找是否存在拆分视图(蓝色)和任何子视图控件以显示另一个视图(红色)的 iOS UIView 转换) 及其控件。我发现有几篇帖子提到了 2011 年的类似内容,但最近没有,所以想知道现在我们升级到 iOS 8 时是否添加了任何新内容。任何指针都将不胜感激。

【问题讨论】:

    标签: ios uiview uiviewcontroller transition uiviewanimationtransition


    【解决方案1】:

    如果您尝试进行这种拆分转换,我已经为视图控制器转换创建了一个动画控制器。如果你看代码,你会发现可以有两种不同的过渡方式,从中间打开 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)
        }
    }
    

    代码可能稍长,但必须易于理解。如果你愿意,可以稍微调整一下。

    【讨论】:

      【解决方案2】:

      iOS 中没有这样的内置过渡。你必须自己做。一种方法是使用UIViewControllerAnimatedTransitioning 协议并进行自定义演示。自定义动画对象执行的动画步骤是这样的,

      1) 创建两个蓝色视图的半图像,并将它们添加到transitionContextcontainerView (您不能将 UIView 分成两半,因此您需要使用它的图像代替)

      2) 将红色控制器的视图添加到半图像下方的transitionContextcontainerView

      3) 移除蓝色视图

      4) 通过动画约束常量值将两个半图像滑离屏幕。

      【讨论】:

        【解决方案3】:

        你可以使用类似的东西:

        UIView *redView = [[UIView alloc]initWithFrame:CGRectMake(self.view.frame.size.width / 2, 0, 1, self.view.frame.size.height)];
        redView.backgroundColor = [UIColor redColor];
        [self.view addSubview:redView];
        
        [UIView animateWithDuration:1 animations:^{
                redView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
        } completion:^(BOOL finished) {
                UIViewController2 *viewController = [UIViewController2 new];
               [self presentViewController:viewController animated:NO completion:^{
                [redView removeFromSuperview];
            }];   
        }];
        

        点击按钮。

        【讨论】:

          猜你喜欢
          • 2012-10-28
          • 1970-01-01
          • 1970-01-01
          • 2013-06-27
          • 1970-01-01
          • 1970-01-01
          • 2011-08-01
          • 1970-01-01
          相关资源
          最近更新 更多