Представление View Controller с эффектом размытия
Я представляю View Controller модально с эффектом размытия фона. iOS 10/XCode 8 представил проблему с моей анимацией. Это код презентации:
let modalVC = ModalViewController(nibName: "ModalViewController", bundle: nil)
modalVC.modalTransitionStyle = .CrossDissolve
modalVC.modalPresentationStyle = .OverFullScreen
presentViewController(modalVC, animated: true, completion: nil)
Добавление размытия на viewDidLoad()
функция в ModalViewController:
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
с эффектом темного размытия. Пробовал как программно с предыдущим фрагментом, так и в Интерфейсном Разработчике.
На iOS 8 и 9 .CrossDissolve
Переход позаботился о "затухании", но после тестирования на iOS 10 (как на устройстве, так и на симуляторе) вид отображается с темным полупрозрачным цветом фона вместо размытия.
После .CrossDissolve
анимация заканчивается, цвет фона меняется на фактический эффект размытия фона. Есть идеи, почему это происходит?
Также попытался добавить layoutIfNeeded()
в начале и в конце viewDidLoad()
для контроллера модального вида без какой-либо удачи. Я использую Swift 2.3
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
}
}
Единственный правильный способ - создать пользовательский модальный переход и свойство анимации эффекта. Смотрите /questions/19600473/uivisualeffectview-v-ios-10/19600486#19600486
Прежде всего, я рассматриваю это решение как временный обходной путь, потому что я должен предположить, что это недавно введенное поведение является ошибкой и будет исправлено в будущих обновлениях. Это делает его немного менее заметным, так как эффект размытия появляется во время анимации, а не после. Все еще не так хорошо, как в iOS 9 и в обратном направлении, но немного лучше.
Представленный контроллер представления без анимации:
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 } }