导航栏转场与 IOS 音乐 App 相同

Posted

技术标签:

【中文标题】导航栏转场与 IOS 音乐 App 相同【英文标题】:Transitions in navigation bar same as IOS Music App 【发布时间】:2016-07-20 17:16:34 【问题描述】:

我们怎样才能得到这个导航栏的过渡效果?? (与苹果的音乐应用相同)

IMAGE1

在这张图片中,我们有一个完全透明的导航栏,只有导航栏按钮可见

IMAGE2

当你向上滚动条变得模糊 当你向下滚动时,栏变得不那么模糊了

IMAGE3

并且在某一点之后导航栏变成了默认的导航栏,里面有Title

任何人都可以指导我如何实现上述过渡效果

我现在拥有的是

    func addBlurEffect() 
    // Add blur view
    var bounds = self.navigationController?.navigationBar.bounds as CGRect!
    visualEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .Dark))
    bounds.offsetInPlace(dx: 0.0, dy: -20.0)
    bounds.size.height = bounds.height + 20.0
    visualEffectView.frame = bounds
    visualEffectView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
    self.navigationController?.navigationBar.addSubview(visualEffectView)


    self.navigationController?.navigationBar.sendSubviewToBack(visualEffectView)

 

我可以模糊我的酒吧,但我希望它在 ios 中作为音乐应用程序模糊

【问题讨论】:

必须成为 Justin Beaver :-) 【参考方案1】:

关键是使用滚动偏移来设置visualEffectView.的alpha 然后当图像从完全离开屏幕到navbar的高度时,你从透明导航栏切换到正常的半透明导航栏。我创建了一个可以使用UIScrollView 执行此操作的视图控制器类,但同样的原理适用于UITableViewUICollectionView

import UIKit

class NavigationBlurViewController: UIViewController, UIScrollViewDelegate 

    // Might not want to hard code the height of the navBar but YOLO
    let navBarHeight: CGFloat = 66.0

    lazy var scrollView: UIScrollView = 
        let scrollView = UIScrollView()
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        return scrollView
    ()

    let contentView = UIView()

    let imageView: UIImageView = 
        let imageView = UIImageView()
        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.image = UIImage(named: "Swift")
        imageView.clipsToBounds = true
        imageView.contentMode = .ScaleAspectFill
        return imageView
    ()

    lazy var visualEffectView: UIVisualEffectView = 
        let blurEffect = UIBlurEffect(style: .Light)
        let visualEffectView = UIVisualEffectView(effect: blurEffect)
        visualEffectView.translatesAutoresizingMaskIntoConstraints = false
        visualEffectView.alpha = 0.0
        return visualEffectView
    ()

    override func viewDidLoad()
    
        super.viewDidLoad()
        self.view.addSubview(self.scrollView)
        self.scrollView.addSubview(self.contentView)
        self.contentView.addSubview(self.imageView)
        self.contentView.addSubview(self.visualEffectView)

        self.navigationController?.navigationBar.setBackgroundImage(UIImage(), forBarMetrics: UIBarMetrics.Default)
        self.navigationController?.navigationBar.shadowImage = UIImage()
        self.navigationController?.navigationBar.tintColor = UIColor.blackColor()

    

    override func updateViewConstraints()
    
        super.updateViewConstraints()
        self.scrollView.topAnchor.constraintEqualToAnchor(self.view.topAnchor).active = true
        self.scrollView.leadingAnchor.constraintEqualToAnchor(self.view.leadingAnchor).active = true
        self.scrollView.trailingAnchor.constraintEqualToAnchor(self.view.trailingAnchor).active = true
        self.scrollView.bottomAnchor.constraintEqualToAnchor(self.view.bottomAnchor).active = true

        self.imageView.topAnchor.constraintEqualToAnchor(self.contentView.topAnchor, constant: -navBarHeight).active = true
        self.imageView.leadingAnchor.constraintEqualToAnchor(self.contentView.leadingAnchor).active = true
        self.imageView.trailingAnchor.constraintEqualToAnchor(self.contentView.trailingAnchor).active = true
        // 150.0 or however tall you want your image
        self.imageView.heightAnchor.constraintEqualToConstant(150.0 + navBarHeight).active = true

        self.visualEffectView.centerXAnchor.constraintEqualToAnchor(self.imageView.centerXAnchor).active = true
        self.visualEffectView.centerYAnchor.constraintEqualToAnchor(self.imageView.centerYAnchor).active = true
        self.visualEffectView.widthAnchor.constraintEqualToAnchor(self.imageView.widthAnchor).active = true
        self.visualEffectView.heightAnchor.constraintEqualToAnchor(self.imageView.heightAnchor).active = true
    

    override func viewDidAppear(animated: Bool) 
        super.viewDidAppear(animated)
        scrollView.delegate = self
    

    override func viewDidLayoutSubviews()
    
        super.viewDidLayoutSubviews()

        // Height just 1000 for example
        self.scrollView.contentSize = CGSize(width: self.view.bounds.width, height: 1000.0)
        self.contentView.frame = CGRect(x: 0.0, y: 0.0, width: self.scrollView.contentSize.width, height: self.scrollView.contentSize.height)

    

    func scrollViewDidScroll(scrollView: UIScrollView)
    
        // Decrease size of denominator to make it blur faster
        self.visualEffectView.alpha = scrollView.contentOffset.y * 1.0 / (self.imageView.frame.height - (2.0 * navBarHeight))

        if scrollView.contentOffset.y > (self.imageView.frame.height - (2.0 * navBarHeight)) && self.navigationController?.navigationBar.backgroundImageForBarMetrics(UIBarMetrics.Default) != nil
        
            self.navigationController?.navigationBar.setBackgroundImage(nil, forBarMetrics: UIBarMetrics.Default)
            self.navigationController?.navigationBar.shadowImage = nil
        
        else if scrollView.contentOffset.y < (self.imageView.frame.height - (2.0 * navBarHeight)) && self.navigationController?.navigationBar.backgroundImageForBarMetrics(UIBarMetrics.Default) == nil
        
            self.navigationController?.navigationBar.setBackgroundImage(UIImage(), forBarMetrics: UIBarMetrics.Default)
            self.navigationController?.navigationBar.shadowImage = UIImage()
        
    

大部分效果逻辑都在scrollViewDidScroll中。您从图像视图上的效果视图开始,但随着 y 偏移的增加完全透明,您会增加不透明度,反之亦然。一旦你到达一个点,只剩下导航栏的高度用于图像切换到UINavigationBar的默认背景,否则使用UIImage()使其透明。

结果是:

或 gif here

显然,Apple Music 会进行其他图像处理来获得柔和的晕影,您可能需要使用这些值来获得您想要的方式,但这应该可以让您大部分时间到达那里。

【讨论】:

嘿伙计,非常感谢您的努力。虽然它的工作非常好和很好的解释,到目前为止,我了解到我们必须向 imageView 而不是 NavigationBar 添加模糊,并且在滚动某个点之后,我们必须使我们的透明 NavigationBar 成为默认 NavigationBar(如果我错了,请纠正我) 您不会将模糊添加到 imageView 本身。您正在放置一个UIVisualEffectView,它将模糊其下方的所有视图。由于图像视图在下方,因此变得模糊。调整 UIVisualEffectView 的 alpha 会产生模糊输入/模糊效果。你关掉导航栏是正确的。查看 Apple Music 应用程序,它们还具有图像视差效果,并且可能出于性能原因,它们可能仅在图像底部具有视觉效果视图。

以上是关于导航栏转场与 IOS 音乐 App 相同的主要内容,如果未能解决你的问题,请参考以下文章

iOS - 仅在一个视图上隐藏导航栏?

iOS 状态栏和导航栏颜色相同

iOS 超 Easy 实现 渐变导航栏

iOS:SWRevealViewController 打开没有导航栏的 WebView 控件

禁用转场动画

如何匹配导航栏与状态栏ios7