質問失礼します。
遷移元にある特定のイメージビューやラベルをそれぞれ個別のアニメーションをさせて画面遷移したいのですが、
遷移先のラベルをせり上がるアニメーションで遷移後の画面のラベル位置で止めようとすると、
gif画像の様に位置にズレが発生してしまいます。
アニメーション時の
animationLabel.frame = secondViewController.secondLabel.frame.offsetBy(dx:0, dy:0)
こちらのコード記載で、次画面にあるラベルと同じサイズ・位置が指定出来ていると考えているのですが、
そうすると位置は指定出来てもframeのサイズ変更の指定はどうすればいいのかも分からず、
いまいちアニメーションの指定方法が理解出来ずにいます。
どなたかご教授いただけますと嬉しいです。
よろしくお願い致します。
・遷移元のビューコントローラー
Swift
1import UIKit 2 3class ViewController: UIViewController, UIViewControllerTransitioningDelegate { 4 5 let loginTransition = LoginTransition() 6 7 @IBAction func loginButton(_ sender: Any) { 8 9 let topVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(identifier: "top") 10 11 topVC.modalPresentationStyle = .overCurrentContext 12 topVC.transitioningDelegate = loginTransition 13 14 present(topVC, animated: true, completion: nil) 15 } 16 17 18 @IBOutlet weak var firstImageView: UIImageView! 19 @IBOutlet weak var firstLabel: UILabel! 20 21 override func viewDidLoad() { 22 super.viewDidLoad() 23 24 } 25 }
・遷移先のビューコントローラー
Swift
1import UIKit 2 3class TopViewController: UIViewController{ 4 5 @IBOutlet weak var secondImageView: UIImageView! 6 @IBOutlet weak var secondLabel: UILabel! 7 8 9 10 override func viewDidLoad() { 11 12 super.viewDidLoad() 13 14 secondLabel.font = UIFont.boldSystemFont(ofSize: 40.0) 15 secondLabel.text = "Label" 16 secondLabel.textColor = .white 17 secondLabel.textAlignment = .center 18 19 } 20 21 @IBAction func backButton(_ sender: Any) { 22 23 dismiss(animated: true, completion: nil) 24 } 25}
・カスタムアニメーション用クラス
Swift
1import UIKit 2 3class LoginTransition: NSObject, UIViewControllerTransitioningDelegate, UIViewControllerAnimatedTransitioning { 4 5 var isPresent: Bool = false 6 let duration : TimeInterval = 1 7 8 //画面遷移時の処理 9 func animationController(forPresented presented: UIViewController, 10 presenting: UIViewController, 11 source: UIViewController) -> UIViewControllerAnimatedTransitioning? 12 { 13 isPresent = true 14 return self 15 } 16 //画面に戻ってくる時の処理 17 func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { 18 isPresent = false 19 return self 20 } 21 22 //アニメーションにかかる時間を設定する 23 func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { 24 return duration 25 } 26 27 //遷移時のアニメーションを設定する 28 func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { 29 if isPresent { 30 animatePresentTransition(transitionContext: transitionContext) 31 } else { 32 animateDissmissalTransition(transitionContext: transitionContext) 33 } 34 } 35 36 //画面遷移時のアニメーションの内容を設定する 37 func animatePresentTransition(transitionContext: UIViewControllerContextTransitioning) { 38 39 /// 遷移元ビューコントローラー 40 let firstViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from) as! ViewController 41 /// 遷移先ビューコントローラー 42 let secondViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) as! TopViewController 43 ///コンテナビュー 44 let containerView = transitionContext.containerView 45 46 ///コンテナビューにビューを登録する(遷移元の上に遷移先を乗せる) 47 containerView.insertSubview(secondViewController.view, belowSubview: firstViewController.view) 48 49 //遷移後のビューコントローラーを、予め最後の位置まで移動完了させ非表示にする 50 secondViewController.view.frame = transitionContext.finalFrame(for: secondViewController) 51 secondViewController.view.alpha = 0 52 //遷移後のイメージビューは、アニメーションが完了するまで非表示にする 53 secondViewController.secondImageView.isHidden = true 54 // 遷移元のイメージビューを非表示にする 55 firstViewController.firstImageView.isHidden = true 56 //遷移元のラベルを非表示にする 57 firstViewController.firstLabel.isHidden = true 58 //遷移先のラベルを非表示にする 59 secondViewController.secondLabel.isHidden = true 60 61 //アニメーションさせるラベルを作成する 62 let animationLabel = UILabel() 63 animationLabel.frame = secondViewController.secondLabel.frame.offsetBy(dx: 0, dy: 50) 64 animationLabel.font = UIFont.boldSystemFont(ofSize: 40.0) 65 animationLabel.text = "Label" 66 animationLabel.textColor = .white 67 animationLabel.textAlignment = .center 68 //遷移コンテナに、アニメーション用のラベルを追加する 69 containerView.addSubview(animationLabel) 70 71 // 遷移元のセルのイメージビューからアニメーション用のイメージビューを作成 72 let animationView = UIImageView(image: firstViewController.firstImageView.image) 73 //アニメーションビューの開始位置を指定する 74 //対象のイメージのframeからxとyがどれだけずれているかで位置を決める(0,0なら同じ位置ということなので開始位置になる) 75 animationView.frame = firstViewController.firstImageView.frame.offsetBy(dx: 0, dy: 0) 76 77 //遷移コンテナに、アニメーション用のイメージビューを追加する 78 containerView.addSubview(animationView) 79 80 //アニメーションを実装する(引数に秒数・アニメーションのクロージャ・完了後のクロージャを設定する) 81 UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: { 82 83 // 遷移後のビューを徐々に表示する 84 secondViewController.view.alpha = 1.0 85 animationView.alpha = 0.3 86 //アニメーション用のビューを、遷移後のイメージの位置・サイズ(xとyが0,0なら同じ位置という事になる)までアニメーションする 87 animationView.frame = secondViewController.secondImageView.frame.offsetBy(dx:0, dy:0) 88 //アニメーション用のラベルを遷移後の位置までアニメーションする 89 animationLabel.frame = secondViewController.secondLabel.frame.offsetBy(dx:0, dy:0) 90 91 }, completion: { 92 //アニメーションが終了した後のクロージャ 93 finished in 94 // 遷移後のイメージを表示する 95 secondViewController.secondImageView.isHidden = false 96 // 遷移前のイメージビューの非表示を元に戻す 97 firstViewController.firstImageView.isHidden = false 98 //遷移元のラベルの非表示を元に戻す 99 firstViewController.firstLabel.isHidden = false 100 //遷移先のラベルの非表示を戻す 101 secondViewController.secondLabel.isHidden = false 102 // アニメーション用のビューを削除する 103 animationView.removeFromSuperview() 104 animationLabel.removeFromSuperview() 105 transitionContext.completeTransition(true) 106 }) 107 } 108 109 110 111 112 // 復帰時の処理 113 func animateDissmissalTransition(transitionContext: UIViewControllerContextTransitioning) { 114 115 /// 遷移元ビューコントローラー 116 let firstViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from) as! TopViewController 117 /// 遷移先ビューコントローラー 118 let secondViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) as! ViewController 119 ///コンテナビュー 120 let containerView = transitionContext.containerView 121 122 ///コンテナビューにビューを登録する(遷移元の上に遷移先を乗せる) 123 containerView.insertSubview(firstViewController.view, belowSubview: secondViewController.view) 124 125 //遷移後のビューコントローラーにある移動すべきimageViewを、予め最後の位置まで移動完了させ非表示にする 126 secondViewController.view.frame = transitionContext.finalFrame(for: secondViewController) 127 secondViewController.view.alpha = 0 128 //遷移後のimageは、アニメーションが完了するまで非表示にする 129 secondViewController.firstImageView.isHidden = true 130 // 遷移元のイメージビューを非表示にする 131 firstViewController.secondImageView.isHidden = true 132 133 // 遷移元のセルのイメージビューからアニメーション用のイメージビューを作成 134 let animationView = UIImageView(image: firstViewController.secondImageView.image) 135 //アニメーションビューの開始位置を指定する 136 //対象のイメージのframeからxとyがどれだけずれているかで位置を決める(0,0なら同じ位置ということなので開始位置になる) 137 animationView.frame = firstViewController.secondImageView.frame.offsetBy(dx: 0, dy: 0) 138 139 //遷移コンテナに、アニメーション用のイメージビューを追加する 140 containerView.addSubview(animationView) 141 142 //アニメーションを実装する(引数に秒数・アニメーションのクロージャ・完了後のクロージャを設定する) 143 UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: { 144 145 // 遷移後のビューを徐々に表示する 146 secondViewController.view.alpha = 1.0 147 animationView.alpha = 0.3 148 //アニメーション用のビューを、遷移後のイメージの位置・サイズ(xとyが0,0なら同じ位置という事になる)までアニメーションする 149 animationView.frame = secondViewController.firstImageView.frame.offsetBy(dx:0, dy:0) 150 }, completion: { 151 //アニメーションが終了した後のクロージャ 152 finished in 153 // 遷移後のイメージを表示する 154 secondViewController.firstImageView.isHidden = false 155 // 遷移前のイメージビューの非表示を元に戻す 156 firstViewController.secondImageView.isHidden = false 157 158 // アニメーション用のビューを削除する 159 animationView.removeFromSuperview() 160 transitionContext.completeTransition(true) 161 }) 162 } 163} 164
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/05/18 14:02