interactionControllerForDismissal(UIPercentDrivenInteractiveTransition)

平成30年4月27日(金曜日)

apple(遷移にインタラクティブ性を追加する)
トランジションアニメーションをカスタマイズする

UIPercentDrivenInteractiveTransition オブジェクトは、既存のアニメーターオブジェクトと連携してアニメーションのタイミングを制御します。
割合主導型のインタラクティブアニメーターを設定する

// Add the gesture recognizer to the container view.
UIView* container = [transitionContext containerView];
[container addGestureRecog

平成30年4月26日(木曜日)

前提
① Delegate内で定義!!

extension ViewController: UIViewControllerTransitioningDelegate {
func interactionControllerForDismissal(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
return interactor.hasStarted ? interactor : nil
}
}

② class作成!!

class Interactor: UIPercentDrivenInteractiveTransition {
var hasStarted = false
var shouldFinish = false
}
/*
open func update(_ percentComplete: CGFloat)

open func cancel()

open func finish()
*/

③ 移動量計算、GestureRecognizer内でinteractor.update(progress)してOK!!
@IBAction func handleGesture(_ sender: UIPanGestureRecognizer) {

let percentThreshold:CGFloat = 0.3

// convert y-position to downward pull progress (percentage)
let translation = sender.translation(in: view)
let verticalMovement = translation.y / view.bounds.height
let downwardMovement = fmaxf(Float(verticalMovement), 0.0)
let downwardMovementPercent = fminf(downwardMovement, 1.0)
let progress = CGFloat(downwardMovementPercent)

guard let interactor = interactor else { return }

switch sender.state {
case .began:
interactor.hasStarted = true
dismiss(animated: true, completion: nil)
case .changed:
interactor.shouldFinish = progress > percentThreshold
interactor.update(progress)
case .cancelled:
interactor.hasStarted = false
interactor.cancel()
case .ended:
interactor.hasStarted = false
interactor.shouldFinish
? interactor.finish()
: interactor.cancel()
default:
break
}
}
}

使い方
let interactor = Interactor()
作成し、destinationViewControllerに渡す。

class ViewController: UIViewController {

let interactor = Interactor()

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destinationViewController = segue.destination as? ModalViewController {
destinationViewController.transitioningDelegate = self
destinationViewController.interactor = interactor
}
}

}

追加(参考)
func dismiss(animated flag: Bool,
completion: (() -> Void)? = nil)

(Dismisses the view controller that was presented modally by the view controller.)
(ビューコントローラによってモーダルに表示されたビューコントローラを閉じます)

@IBAction func toSecondVew(){
performSegue(withIdentifier: "toSecond", sender: nil)
}

@IBAction func back(){
self.dismiss(animated: true, completion: nil)
}