5

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

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 XI 中由于“64”作为渐变的导航栏高度而出现问题,如下所示_

在此处输入图像描述

请为此建议一个可以在每种情况下动态使用的修复程序。

4

4 回答 4

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)。

于 2018-02-10T11:14:20.723 回答
2

我已经通过屏幕高度检查了 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])

结果是这样的。就我而言,渐变在导航栏的底部使用 alpha 零

于 2017-10-01T02:49:52.730 回答
2

像这样拉伸图像怎么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)
        }
    }
}
于 2018-12-31T09:03:12.137 回答
0

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

我认为实现您想要做的最简单的方法是将UINavigationController'init(navigationBarClass:toolbarClass:)方法与自定义UINavigationBar子类一起使用,该子类覆盖layerClass以直接指定您的CAGradientLayer

不幸的是,我认为没有办法用UIAppearance.

于 2017-09-22T09:31:27.753 回答