我有一個Storyboard設置,並且在某個時候一個按鈕用另一個按鈕替換了細節視圖。默認情況下,根本沒有轉換:視圖控制器突然被替換。我可以創建一個嗎?動畫替換UISplitViewController中的細節視圖
我的猜測是使用自定義轉換 - 就像您通常爲視圖更改具有自定義動畫一樣 - 但我不知道如何實現分割視圖控制器的「替換」行爲。
我有一個Storyboard設置,並且在某個時候一個按鈕用另一個按鈕替換了細節視圖。默認情況下,根本沒有轉換:視圖控制器突然被替換。我可以創建一個嗎?動畫替換UISplitViewController中的細節視圖
我的猜測是使用自定義轉換 - 就像您通常爲視圖更改具有自定義動畫一樣 - 但我不知道如何實現分割視圖控制器的「替換」行爲。
我做了這個使用自定義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)
})
})
}
}
}
我用Pavel Smejkal's answer,具有以下裝飾:
這裏是修改後的代碼:
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)
})
})
}
}
}