我将以表格视图控制器为根,以模态形式展示导航控制器,并在用户点击一个单元格时推送更多视图控制器。现在,我想对整个对象应用模糊/鲜艳效果。
故事板如下:
现在,要将模糊效果应用于整个导航控制器,以便可以在下面看到初始视图控制器中的图像。
通过对表视图控制器和详细视图控制器应用相同的模糊效果,我已经取得了一些成功,
表视图控制器
class TableViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.tableFooterView = UIView(frame: .zero)
tableView.backgroundColor = UIColor.clear
let blurEffect = UIBlurEffect(style: .dark)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
tableView.backgroundView = blurEffectView
tableView.separatorEffect = UIVibrancyEffect(blurEffect: blurEffect)
}
}
详细视图控制器
class DetailViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .clear
let blurEffect = UIBlurEffect(style: .dark)
let blurView = UIVisualEffectView(effect: blurEffect)
blurView.translatesAutoresizingMaskIntoConstraints = false
view.insertSubview(blurView, at: 0)
NSLayoutConstraint.activate([
blurView.heightAnchor.constraint(equalTo: view.heightAnchor),
blurView.widthAnchor.constraint(equalTo: view.widthAnchor),
])
}
}
(我还将导航的模式显示样式设置为.overFullScreen
)。
但是,在导航到详细信息视图控制器的最后,在模糊的背景中可以看到烦人的人工产物:
我认为,这与自iOS 7开始,推送视图控制器不能具有透明背景有关,否则可以看到推送视图控制器,因为它在过渡结束时立即被移除了。
我尝试将模糊效果应用于导航控制器,并改为使两个孩子的视图都透明,但效果也不佳。
将背景模糊/鲜艳效果无缝应用于导航控制器内容的正确方法是什么?
答案 0 :(得分:1)
尝试以下步骤。我没有尝试过,但应该可以。
didFinishLaunchingWithOptions
的窗口中,并默认将其隐藏。让我知道您是否需要任何帮助。
答案 1 :(得分:0)
正如我在问题中指出的那样,自iOS 7以来引入的推送/弹出动画过渡(其中导航堆栈中较低的视图控制器“以一半的速度滑出”,因此(它比被推入/弹出的窗口要小)。无法在没有构件的透明视图控制器之间进行转换。
因此,我决定采用协议UINavigationControllerDelegate
,更确切地说是方法:navigationController(_:animationControllerFor:from:to:)
,从头开始基本上复制UINavigationController的动画过渡。
这使我可以在推操作期间从过渡移开的视图中添加mask view,以便裁剪下重叠部分,并且不会出现可见的伪像。
到目前为止,我仅实现了 push 操作(最终,我也必须执行pop操作,还需要基于手势的弹出式交互转换)。 / strike> 我已经创建了一个自定义的UINavigationController
子类和put it on GitHub。
(目前,它支持动画推送和弹出,但不支持交互性。而且,我还没有弄清楚如何复制导航栏标题的“幻灯片”动画-它只是交叉溶解。)
它可以归纳为以下步骤:
.to
视图转换到屏幕外的右侧。在动画过程中,逐渐将其转换回身份(屏幕中心)。mask
视图,.from
的边界最初等于.from
视图(无遮罩)。在动画过程中,逐渐将蒙版的frame
属性的宽度减小到其初始值的一半。from
视图逐渐移出屏幕一半,向左移。在代码中:
class AnimationController: NSObject, UIViewControllerAnimatedTransitioning {
// Super slow for debugging:
let duration: TimeInterval = 1
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return duration
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard let fromView = transitionContext.view(forKey: .from) else {
return
}
guard let toView = transitionContext.view(forKey: .to) else {
return
}
guard let toViewController = transitionContext.viewController(forKey: .to) else {
return
}
//
// (Code below assumes navigation PUSH operation. For POP,
// use similar code but with view roles and direction
// reversed)
//
// Add target view to container:
transitionContext.containerView.addSubview(toView)
// Set tagret view frame, centered on screen
let toViewFinalFrame = transitionContext.finalFrame(for: toViewController)
toView.frame = toViewFinalFrame
let containerBounds = transitionContext.containerView.bounds
toView.center = CGPoint(x: containerBounds.midX, y: containerBounds.midY)
// But translate it to fully the RIGHT, for now:
toView.transform = CGAffineTransform(translationX: containerBounds.width, y: 0)
// We will slide the source view out, to the LEFT, by half as much:
let fromTransform = CGAffineTransform(translationX: -0.5*containerBounds.width, y: 0)
// Apply a white UIView as mask to the source view:
let maskView = UIView(frame: CGRect(origin: .zero, size: fromView.frame.size))
maskView.backgroundColor = .white
fromView.mask = maskView
// The mask will shrink to half the width during the animation:
let maskViewNewFrame = CGRect(origin: .zero, size: CGSize(width: 0.5*fromView.frame.width, height: fromView.frame.height))
// Animate:
UIView.animate(withDuration: duration, delay: 0, options: [.curveEaseOut], animations: {
fromView.transform = fromTransform // off-screen to the left (half)
toView.transform = .identity // Back on screen, fully centered
maskView.frame = maskViewNewFrame // Mask to half width
}, completion: {(completed) in
// Remove mask, or funny things will happen to a
// table view or scroll view if the user
// "rubber-bands":
fromView.mask = nil
transitionContext.completeTransition(completed)
})
}
(为清楚起见,我向详细视图控制器添加了文本视图)