如何将 CAGradientLayer 应用于 UINavigationController 背景 [英] How can I apply CAGradientLayer to a UINavigationController background

查看:26
本文介绍了如何将 CAGradientLayer 应用于 UINavigationController 背景的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有 prefersLargeTitles = trueUINavigationController 我想将背景颜色应用到我的导航栏,并带有渐变蒙版,因此颜色基本上会淡化为较暗的版本.

I have a UINavigationController with prefersLargeTitles = true I'd like to apply a background colour to my nav bar, with a gradient mask so the colour essentially fades to a darker version.

我尝试创建一个 UIView 应用蒙版并呈现它.然而,这涉及将 UIView 渲染为 UIImage,然后渲染为 UIColor,以便我可以设置 barTintColor.

I have tried to create a UIView apply the mask and render this. This however involves rendering the UIView as a UIImage and then as a UIColor so I can set the barTintColor.

这仅在渲染 UIView 时有效,但在导航栏上设置时,行为不是我想要的.

This works when just rendering a UIView but when setting it on the navigation bar, the behaviour is not as I would like.

我希望渐变填充整个绿色区域.

I would like that gradient to fill the entire green area.

class BaseViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        configureNavigationBar()
    }

    override var preferredStatusBarStyle: UIStatusBarStyle {
        return .lightContent
    }

    func hideNavigationBar() {
        navigationController?.setNavigationBarHidden(true, animated: false)
    }

    func showNavigationBar() {
        navigationController?.setNavigationBarHidden(false, animated: false)
    }

    private func configureNavigationBar() {
        navigationController?.navigationBar.prefersLargeTitles = true
        navigationController?.navigationBar.isTranslucent = false
        navigationItem.title = "Home"

        let v = BrandedHeader(frame: .zero)
        v.frame = navigationController?.navigationBar.frame ?? .zero

        navigationController?.navigationBar.barTintColor = UIColor(patternImage: v.asImage()!)
    }
}

extension UIImage {
    static func usingHex(_ hex: String) -> UIImage {
        let color = UIColor.usingHex(hex)
        let rect = CGRect(x: 0, y: 0, width: 1, height: 1)
        UIGraphicsBeginImageContext(rect.size)
        let context = UIGraphicsGetCurrentContext()
        context!.setFillColor(color.cgColor)
        context!.fill(rect)
        let img = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return img!
    }
}

extension UIView {

    func asImage() -> UIImage? {
        if #available(iOS 10.0, *) {
            let renderer = UIGraphicsImageRenderer(bounds: bounds)
            return renderer.image { rendererContext in
                layer.render(in: rendererContext.cgContext)
            }
        } else {
            UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.isOpaque, 0.0)
            defer { UIGraphicsEndImageContext() }
            guard let currentContext = UIGraphicsGetCurrentContext() else {
                return nil
            }
            self.layer.render(in: currentContext)
            return UIGraphicsGetImageFromCurrentImageContext()
        }
    }
}

class BrandedHeader: UIView {
    let gradient: CAGradientLayer = CAGradientLayer()

    override init (frame: CGRect) {
        super.init(frame: frame)

        backgroundColor = UIColor.green

        gradient.frame = frame
        gradient.colors = [UIColor.clear, UIColor.black.withAlphaComponent(0.3)].map { $0.cgColor }
        gradient.locations = [0.0, 0.7]
        gradient.startPoint = CGPoint(x: 0.0, y: 0.0)
        gradient.endPoint = CGPoint(x: 1.0, y: 0.0)
        layer.insertSublayer(gradient, at: 0)
    }

    required init?(coder aDecoder: NSCoder) {
        return nil
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        gradient.frame = frame
        gradient.removeAllAnimations()
    }
}

推荐答案

为了回答你的问题,我不认为 gradient.frame = frame 在你的 BrandedHeader init 中正在做任何事情.我相信您需要在 layoutSubviews 中明确设置 height 道具.

To answer your question, I don't think gradient.frame = frame in your BrandedHeader init is doing anything. I believe you explicitly need to set the height prop in layoutSubviews.

类似 gradient.frame = CGRect(x: 0, y: 0, width: frame.width, height: 500) - 虽然我没试过,所以请考虑调整值

Something like gradient.frame = CGRect(x: 0, y: 0, width: frame.width, height: 500) - although I haven't tried that so please consider adjusting the values

我不确定这种方法是否是您想要实现的最佳方法,一旦我尝试了另一种方法来实现这一目标,我会回来更新这个答案.

I'm not sure if this approach is the best approach for what you are trying to achieve, I will comeback and update this answer once I have tried another way to achieve this.

这篇关于如何将 CAGradientLayer 应用于 UINavigationController 背景的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆