背景をぼかす効果のあるビューコントローラーをモーダルに表示しています。 iOS 10/XCode8でアニメーションに問題が発生しました。これはプレゼンテーションコードです:
_let modalVC = ModalViewController(nibName: "ModalViewController", bundle: nil)
modalVC.modalTransitionStyle = .CrossDissolve
modalVC.modalPresentationStyle = .OverFullScreen
presentViewController(modalVC, animated: true, completion: nil)
_
ModalViewControllerのviewDidLoad()
関数にぼかしを追加します。
_let blurEffect = UIBlurEffect(style: .Light)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.frame = view.bounds
blurEffectView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
view.addSubview(blurEffectView)
view.sendSubviewToBack(blurEffectView)
_
ModalViewController
の背景ははっきりしていて、ダークブラー効果のあるBlurEffectView
を追加しました。前のスニペットとInterfaceBuilderの両方でプログラムで試しました。
IOS 8および9では、_.CrossDissolve
_トランジションが「フェード」を処理しましたが、iOS 10(デバイスとシミュレーターの両方)でテストした後、ビューはぼやけではなく暗い半透明の背景色で表示されます。
_.CrossDissolve
_アニメーションが終了すると、背景色が実際のぼかし効果の背景に変わります。なぜこれが起こっているのか考えはありますか?
また、運が悪かったので、モーダルビューコントローラのlayoutIfNeeded()
の最初と最後にviewDidLoad()
を追加してみました。私はSwift 2.3を使用しています
新しいUIViewControllerAnimatedTransitioning
を作成する必要があります。
次に、animateTransition(using transitionContext: UIViewControllerContextTransitioning)
でアニメーションをコーディングする必要があります。
IOS 10では、UIViewPropertyAnimator
のBlurRadius
をアニメーション化するためにUIVisualBlurEffect
を使用できるようになりました。
ここに使用例があります: https://github.com/PierrePerrin/PPBlurModalPresentation
ぼかし遷移を作成する必要があります
class BlurModalPresentation: NSObject,UIViewControllerAnimatedTransitioning {
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval{
return 0.5
}
//This is the blur view used for transition
var blurView = UIVisualEffectView(effect: UIBlurEffect(style: UIBlurEffectStyle.light))
var destinationView : UIView!
var animator: UIViewPropertyAnimator?
// This method can only be a nop if the transition is interactive and not a percentDriven interactive transition.
func animateTransition(using transitionContext: UIViewControllerContextTransitioning){
let containerView = transitionContext.containerView
_ = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)
let toVc = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)
destinationView = toVc!.view
destinationView.alpha = 0.0
//Here we add the blur view and set it effect to nil
blurView.effect = nil
blurView.frame = containerView.bounds
self.blurTransition(transitionContext) {
self.unBlur(transitionContext, completion: {
self.blurView.removeFromSuperview()
transitionContext.completeTransition(true)
})
}
containerView.addSubview(toVc!.view)
containerView.addSubview(blurView)
}
//This methods add the blur to our view and our destinationView
func blurTransition(_ context : UIViewControllerContextTransitioning,completion: @escaping () -> Void){
UIViewPropertyAnimator.runningPropertyAnimator(withDuration: self.transitionDuration(using: context)/2, delay: 0, options: UIViewAnimationOptions.curveLinear, animations: {
self.destinationView.alpha = 0.5
self.blurView.effect = UIBlurEffect(style: UIBlurEffectStyle.light)
}, completion: { (position) in
completion()
})
}
//This Method remove the blur view with an animation
func unBlur(_ context : UIViewControllerContextTransitioning,completion: @escaping () -> Void){
UIViewPropertyAnimator.runningPropertyAnimator(withDuration: self.transitionDuration(using: context) / 2, delay:0, options: UIViewAnimationOptions.curveLinear, animations: {
self.destinationView.alpha = 1.0
self.blurView.effect = nil
}, completion: { (position) in
completion()
})
}
}
ViewController
で移行する委任を設定する必要があります。
import UIKit
class ViewController: UIViewController,UIViewControllerTransitioningDelegate {
let blurModalPresentation = BlurModalPresentation()
override func viewDidLoad() {
super.viewDidLoad()
}
func showVC(){
let str = self.storyboard!
let vc = str.instantiateViewController(withIdentifier: "YourViewControllerIdentifier")
vc.transitioningDelegate = self
self.present(vc, animated: true, completion: nil)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning?{
return blurModalPresentation
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning?{
return blurModalPresentation
}
}
まず、この新たに導入された動作はバグであり、将来のアップデートで修正されると想定する必要があるため、このソリューションを一時的な回避策と見なしています。これにより、アニメーションの後でではなくアニメーション中にぼかし効果が現れるため、少し目立たなくなります。それでもiOS9以降ほど良くはありませんが、少し良くなっています。
アニメーションなしの現在のViewController:
presentViewController(modalVC, animated: false, completion: nil)
最初からビューを非表示にします。
override func viewDidLoad() {
super.viewDidLoad()
view.alpha = 0
}
アニメーションを手動で適用します。
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
UIView.animateWithDuration(0.25) {
self.view.alpha = 1
}
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
UIView.animateWithDuration(0.25) {
self.view.alpha = 0
}
}
唯一の正しい方法は、カスタムのモーダルトランジションを作成してエフェクトプロパティをアニメーション化することです。 https://stackoverflow.com/a/3970974 を参照してください