概要
ナビゲーションコントローラーでの画面遷移アニメーションを変更する。
実装環境
Xcode 10.1
Swift 4.2.1
コード
先ずは通常の画面遷移
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var navigationController: UINavigationController?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let viewController: ViewController = ViewController()
//set viewController as rootViewController of navi
navigationController = UINavigationController(rootViewController: viewController)
//hide navigation bar
navigationController?.setNavigationBarHidden(true, animated: false)
//set window
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window!.backgroundColor = .white
//set navi as rootViewController
self.window!.rootViewController = navigationController
self.window!.makeKeyAndVisible()
return true
}
func applicationWillResignActive(_ application: UIApplication) {
}
func applicationDidEnterBackground(_ application: UIApplication) {
}
func applicationWillEnterForeground(_ application: UIApplication) {
}
func applicationDidBecomeActive(_ application: UIApplication) {
}
func applicationWillTerminate(_ application: UIApplication) {
}
}
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
createImage()
createButton()
}
func createImage() {
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height))
imageView.image = UIImage(named: "image1")
imageView.contentMode = .scaleAspectFill
self.view.addSubview(imageView)
}
func createButton(){
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 50))
button.center = self.view.center
button.setTitle("next", for: .normal)
button.backgroundColor = UIColor(red: 200/255, green: 200/255, blue: 200/255, alpha: 1.0)
button.addTarget(self, action: #selector(onButtonTapped), for: .touchUpInside)
self.view.addSubview(button)
}
@objc func onButtonTapped(){
/* if you want to use default transitions, please uncomment out below. */
//let transition = CATransition()
//transition.duration = 0.5
//transition.type = CATransitionType.fade
//following types are used with subtype
//transition.type = CATransitionType.moveIn
//transition.type = CATransitionType.push
//transition.type = CATransitionType.reveal
//example of subtype
//transition.subtype = CATransitionSubtype.fromBottom
//navigationController?.view.layer.add(transition, forKey: nil)
let view = UIView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height))
view.alpha = 0
view.backgroundColor = .white
self.view.addSubview(view)
UIWindow.animate(withDuration: 1.0, animations: {
view.alpha = 1.0
}) { (Bool) in
DispatchQueue.main.asyncAfter(deadline: .now()+0.2, execute: {
//Attention "animated" is "false"
self.navigationController?.pushViewController(nextViewController(), animated: false)
})
DispatchQueue.main.asyncAfter(deadline: .now()+1.0, execute: {
view.removeFromSuperview()
})
}
}
}
import UIKit
class nextViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
createImage()
createButton()
}
func createImage() {
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height))
imageView.image = UIImage(named: "image2")
imageView.contentMode = .scaleAspectFill
self.view.addSubview(imageView)
}
func createButton(){
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 50))
button.center = self.view.center
button.setTitle("back", for: .normal)
button.backgroundColor = UIColor(red: 200/255, green: 200/255, blue: 200/255, alpha: 1.0)
button.addTarget(self, action: #selector(onButtonTapped), for: .touchUpInside)
self.view.addSubview(button)
}
@objc func onButtonTapped(){
let view = UIView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height))
view.alpha = 0
view.backgroundColor = .white
self.view.addSubview(view)
UIWindow.animate(withDuration: 1.0, animations: {
view.alpha = 1.0
}) { (Bool) in
DispatchQueue.main.asyncAfter(deadline: .now()+0.2, execute: {
//Attention not pushViewController
//popToViewController is back ViewController method
self.navigationController?.popToViewController(self.navigationController!.viewControllers[0], animated: false)
})
DispatchQueue.main.asyncAfter(deadline: .now()+1.0, execute: {
view.removeFromSuperview()
})
}
}
}
結果
解説
今回の実装ではstoryboardを使わなかったためstoryboardのファイルは削除している。
それなのでInfo.plistからstoryboard file base nameを削除しAppDelegateでwindowを設定した。
遷移アニメーションの変更部分
navigationControllerのanimatedをfalseにすることで横にスライドするアニメーションを行わないようにする。
self.navigationController?.pushViewController(nextViewController(), animated: false)
その他のやり方
コメントアウトしているところを参考にしてもらえれば分かるようにnavigationControllerのtypeを変更することで遷移方法を変更できる。
segueのcross dissolveのようなanimationであればtypeをfadeにすることで簡単に実装できるだろう。
参考
[CATransition]
(https://developer.apple.com/documentation/quartzcore/catransition)
[How do I cross dissolve when pushing views on a UINavigationController in iOS 7?]
(https://stackoverflow.com/questions/23530538/how-do-i-cross-dissolve-when-pushing-views-on-a-uinavigationcontroller-in-ios-7)
[How do I create a new Swift project without using Storyboards?]
(https://stackoverflow.com/questions/24046898/how-do-i-create-a-new-swift-project-without-using-storyboards)