Animate替换UISplitViewController中的Detail View

时间:2015-02-18 00:35:59

标签: objective-c uisplitviewcontroller transitions

我有一个故事板设置,在某个时刻,一个按钮将详细视图替换为另一个。默认情况下,根本没有转换:View Controller突然被替换。我可以创建一个以及如何创建?

我的猜测是使用自定义转换 - 就像您通常为视图更改设置自定义动画一样 - 但我不知道如何实现拆分视图控制器的“替换”行为。

2 个答案:

答案 0 :(得分:1)

我使用自定义segue做了这个,当有splitViewController时,我做“显示细节”,否则我尝试推送/呈现模态。全部动画。节目模态动画将使用变换淡出旧控制器并显示具有变换的新控制器

class ShowDetailSegue: UIStoryboardSegue {

    private let showFromScale : CGFloat = 0.8
    private let hideToScale : CGFloat = 1.2
    private let animationDuration : NSTimeInterval = 0.33

    override func perform() {

        let sourceVC = self.sourceViewController as! UIViewController
        let destinationVC = self.destinationViewController as! UIViewController
        let animated = true

        if let splitVC = sourceVC.splitViewController where splitVC.isInSplitView {
            // splitview with detail is visible, we will show detail with animation
            showDetail(splitVC, sourceVC : sourceVC, destinationVC: destinationVC, animated: animated)
        } else if let navController = sourceVC.navigationController {
            // there is no split view – just push to navigation controller
            sourceVC.navigationController?.pushViewController(destinationVC, animated: animated)
        } else {
            // no navigation found, let just present modal
            sourceVC.presentViewController(destinationVC, animated: animated, completion: nil)
        }

    }

    private func showDetail(splitVC : UISplitViewController, sourceVC : UIViewController, destinationVC : UIViewController, animated : Bool) {

        let newDetailVC = GeneralNavigationController(rootViewController: destinationVC)
        newDetailVC.applyAppearance()

        if !animated {

            splitVC.showDetailViewController(newDetailVC, sender: sourceVC)

        } else {

            var currentDetailVC = splitVC.viewControllers.last as! UIViewController

            if let currentDetailNC = currentDetailVC as? UINavigationController {
                currentDetailVC = currentDetailNC.topViewController
            }

            UIView.animateWithDuration(animationDuration / 2.0, animations: { () -> Void in
                // hide the old view with transform

                currentDetailVC.view.alpha = 0
                currentDetailVC.view.transform = CGAffineTransformMakeScale(self.hideToScale, self.hideToScale)
                currentDetailVC.navigationController?.navigationBar.alpha = 0

                }, completion: { (completed) -> Void in

                    newDetailVC.navigationController?.navigationBar.alpha = 0
                    newDetailVC.view.alpha = 0
                    newDetailVC.view.transform = CGAffineTransformScale(newDetailVC.view.transform, self.showFromScale, self.showFromScale)

                    splitVC.showDetailViewController(newDetailVC, sender: sourceVC)

                    // Show new view

                    UIView.animateWithDuration(self.animationDuration / 2.0, animations: { () -> Void in

                        newDetailVC.view.alpha = 1
                        newDetailVC.view.transform = CGAffineTransformScale(newDetailVC.view.transform, 1 / self.showFromScale, 1 / self.showFromScale)

                        newDetailVC.navigationController?.navigationBar.alpha = 1

                        }, completion: { (completed) -> Void in

                            currentDetailVC.view.transform = CGAffineTransformScale(currentDetailVC.view.transform, 1 / self.hideToScale, 1 / self.hideToScale)
                    })
            })


        }


    }

}

答案 1 :(得分:0)

我使用了Pavel Smejkal's answer,其中包含以下内容:

  • 新的细节控制器可能已嵌入到 UINavigationController,所以我检查了
  • 我拿出他的习俗的参考 导航控制器类
  • 我将它转换为Swift 3

以下是修订后的代码:

import UIKit

class SegueShowDetail: UIStoryboardSegue {

    private let showFromScale: CGFloat = 0.8
    private let hideToScale: CGFloat = 1.2
    private let animationDuration: TimeInterval = 0.33

    override func perform() {

        let sourceVC = self.source 
        let destinationVC = self.destination 
        let animated = true

        if let splitVC = sourceVC.splitViewController, !splitVC.isCollapsed {

            // splitview with detail is visible, we will show detail with animation
            showDetail( splitVC: splitVC, sourceVC : sourceVC, destinationVC: destinationVC, animated: animated )

        } else if let navController = sourceVC.navigationController {

            // there is no split view – just push to navigation controller
            sourceVC.navigationController?.pushViewController( destinationVC, animated: animated )

        } else {
            // no navigation found, let just present modal
            sourceVC.present( destinationVC, animated: animated, completion: nil )
        }

    }

    fileprivate func showDetail( splitVC : UISplitViewController, sourceVC : UIViewController, destinationVC : UIViewController, animated : Bool ) {

        var navController: UINavigationController? = destinationVC as? UINavigationController
        if nil == navController {

            navController = UINavigationController( rootViewController: destinationVC )
        }

        guard let newDetailNavVC = navController else {

            return
        }

        if !animated {

            splitVC.showDetailViewController( newDetailNavVC, sender: sourceVC )

        } else {

            var currentDetailVC = splitVC.viewControllers.last!

            if let currentDetailNC = currentDetailVC as? UINavigationController {
                currentDetailVC = currentDetailNC.topViewController!
            }

            UIView.animate(withDuration: animationDuration / 2.0, animations: { () -> Void in
                // hide the old view with transform

                currentDetailVC.view.alpha = 0
                currentDetailVC.view.transform = CGAffineTransform(scaleX: self.hideToScale, y: self.hideToScale)
                currentDetailVC.navigationController?.navigationBar.alpha = 0

            }, completion: { (completed) -> Void in

                newDetailNavVC.navigationController?.navigationBar.alpha = 0
                newDetailNavVC.view.alpha = 0
                newDetailNavVC.view.transform = newDetailNavVC.view.transform.scaledBy( x: self.showFromScale, y: self.showFromScale )

                splitVC.showDetailViewController( newDetailNavVC, sender: sourceVC)

                // Show new view

                UIView.animate( withDuration: self.animationDuration / 2.0, animations: { () -> Void in

                    newDetailNavVC.view.alpha = 1
                    newDetailNavVC.view.transform = newDetailNavVC.view.transform.scaledBy( x: 1 / self.showFromScale, y: 1 / self.showFromScale )

                    newDetailNavVC.navigationController?.navigationBar.alpha = 1

                }, completion: { (completed) -> Void in

                    currentDetailVC.view.transform = currentDetailVC.view.transform.scaledBy( x: 1 / self.hideToScale, y: 1 / self.hideToScale)
                })
            })
        }
    }
}