处理iPhone X中的导航栏背景渐变

时间:2017-09-22 09:12:52

标签: ios swift iphone-x

到目前为止,我通过以下方式处理导航栏中的渐变_

let gradient = CAGradientLayer()
    let sizeLength = UIScreen.main.bounds.size.height * 2
    let defaultNavigationBarFrame = CGRect(x: 0, y: 0, width: sizeLength, height: 64)
    gradient.frame = defaultNavigationBarFrame
    gradient.colors = [UIColor(hex:"92CF1F").cgColor, UIColor(hex:"79AB1B").cgColor]

    UINavigationBar.appearance().setBackgroundImage(self.image(fromLayer: gradient), for: .default)
    UINavigationBar.appearance().tintColor = UIColor.white
    UINavigationBar.appearance().isTranslucent = false
    UINavigationBar.appearance().clipsToBounds = false

    if DeviceType.IS_IPAD{
        UINavigationBar.appearance().titleTextAttributes = [NSFontAttributeName : UIFont .systemFont(ofSize: 24, weight: UIFontWeightLight), NSForegroundColorAttributeName: UIColor.white]
    }
    else
    {
        UINavigationBar.appearance().titleTextAttributes = [NSFontAttributeName : UIFont .systemFont(ofSize: 20, weight: UIFontWeightLight), NSForegroundColorAttributeName: UIColor.white]
    }

    UISearchBar.appearance().backgroundColor = UIColor.clear

但是现在在iPhone X中我有问题,因为“64”作为梯度的导航栏高度如下_

enter image description here

请建议针对此进行修复,以便在每种情况下动态使用。

4 个答案:

答案 0 :(得分:4)

使用Alisson Barauna对您的问题的回答,我设法通过更新我的UINavigationBar扩展来解决这个问题,如下所示:

extension UINavigationBar {

@objc func setGradientBackground(colors: [UIColor]) {

    var updatedFrame = bounds

    if UIDevice().userInterfaceIdiom == .phone {
        if UIScreen.main.nativeBounds.height == 2436{
            updatedFrame.size.height += 44
        } else {
            updatedFrame.size.height += 20
        }
    }

    let gradientLayer = CAGradientLayer(frame: updatedFrame, colors: colors)
    setBackgroundImage(gradientLayer.createGradientImage(), for: UIBarMetrics.default)
}

通过这样做,如果程序检测到正在使用iPhone X(屏幕高度为2436),则高度将设置为较大的iPhone X尺寸(44)。

答案 1 :(得分:1)

我已经通过屏幕高度检查了iPhone X模式,然后我更改了生成的渐变图像以填充导航栏。 我认为这不是最好的解决方法,但它现在工作正常。

class func checkiPhoneModel() -> String {
    if UIDevice().userInterfaceIdiom == .phone {
        switch UIScreen.main.nativeBounds.height {
        case 1136:
            return "5, 5s, 5c, se"
        case 1334:
            return "6, 6s, 7"
        case 2208:
            return "6+, 6S+, 7+"
        case 2436:
            return "X"
        default:
            return "unknown"
        }
    }
    return ""
}

然后你可以为UINavigationBar创建一个扩展,添加一个方法来改变渐变图像的颜色:

extension UINavigationBar {

    func setGradientBackground(colors: [UIColor]) {

        var size:CGFloat

        if Reachability.checkiPhoneModel() == "X" {
          size = 44
        }
        else {
            size = 20
        }

        var updatedFrame = bounds
        updatedFrame.size.height += size
        let gradientLayer = CAGradientLayer(frame: updatedFrame, colors: colors)

        setBackgroundImage(gradientLayer.creatGradientImage(), for: UIBarMetrics.default)
    }
}

当iPhone X时,size var设置为44,而其他型号则为20。

然后在viewDidLoad上,只需调用最近创建的方法:

self.navigationController?.navigationBar.setGradientBackground(colors: [.red, .yellow])

The result is something like this. In my case, the gradient uses alpha zero at the bottom of the navigationBar

答案 2 :(得分:0)

您不仅不能再认为导航栏高度为64,而且不能再假设静态高度。

我认为,实现您尝试做的最简单的方法是使用UINavigationController init(navigationBarClass:toolbarClass:)方法和覆盖UINavigationBar的自定义layerClass子类{1}}直接指定您的CAGradientLayer

不幸的是,我认为没有办法解雇和忘记"这与UIAppearance

答案 3 :(得分:0)

如何使用UIImage.resizableImage()拉伸图像,如下所示: (这几乎是完美的解决方案)

open class NavigationController: UINavigationController {

    var gradientColors = [UIColor]() {
        didSet {
            updateGradient()
        }
    }

    open func updateGradient() {
        guard gradientColors.count > 1 else {
            // There has to be at least two colors to set gradient..
            return
        }
        let gradient = CAGradientLayer()
        let defaultNavigationBarFrame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 64)

        gradient.frame = defaultNavigationBarFrame
        gradient.colors = gradientColors.map({ $0.cgColor })

        if let gradientImage = gradient.snapshotImage() {
            let image =  gradientImage.resizableImage(withCapInsets: UIEdgeInsets(top: 1, left: 1, bottom: 1, right: 1), resizingMode: UIImage.ResizingMode.stretch)
            UINavigationBar.appearance().setBackgroundImage(image, for: .default)
        }
    }
}

CALayer.snapshotImage()实现:

public extension CALayer {
    public func snapshotImage() -> UIImage? {
        return UIGraphicsImageRenderer(bounds: frame).image { (imageContext) in
            render(in: imageContext.cgContext)
        }
    }
}