iOS 10自定义导航栏高度

8
我使用以下代码通过子类化实现自定义导航栏高度:

我通过子类化来实现自定义导航栏的高度,代码如下:

class TMNavigationBar: UINavigationBar {

    ///The height you want your navigation bar to be of
    static let navigationBarHeight: CGFloat = 44.0

    ///The difference between new height and default height
    static let heightIncrease:CGFloat = navigationBarHeight - 44

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

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        initialize()
    }

    private func initialize() {
        let shift = TMNavigationBar.heightIncrease/2

        ///Transform all view to shift upward for [shift] point
        self.transform =
            CGAffineTransformMakeTranslation(0, -shift)
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        let shift = TMNavigationBar.heightIncrease/2

        ///Move the background down for [shift] point
        let classNamesToReposition: [String] = ["_UINavigationBarBackground"]
        for view: UIView in self.subviews {
            if classNamesToReposition.contains(NSStringFromClass(view.dynamicType)) {
                let bounds: CGRect = self.bounds
                var frame: CGRect = view.frame
                frame.origin.y = bounds.origin.y + shift - 20.0
                frame.size.height = bounds.size.height + 20.0
                view.frame = frame
            }
        }
    }

    override func sizeThatFits(size: CGSize) -> CGSize {
        let amendedSize:CGSize = super.sizeThatFits(size)
        let newSize:CGSize = CGSizeMake(amendedSize.width, TMNavigationBar.navigationBarHeight);
        return newSize;
    }
}

仅在iOS 10上出现以下问题:(导航栏和视图之间有黑色空白)

输入图像描述

不知道发生了什么。但是在Storyboard中,它生成了此警告,并且没有办法在IB中修复它(只有在我更改IB中导航栏的子类时才会出现警告)。

输入图像描述


1
故事板警告是关于宽度而不是高度的。这与您的代码无关。——问题在哪里?您说“以下问题”,但从未说明是什么问题。 - matt
请查看更新后的截图,它显示视图和导航栏之间有黑色空间。 - Vlad Z.
那么是什么导致了黑色空间呢?导航栏底部太高还是视图顶部太低?你有一个调试器。调试!在这种情况下,使用View Debugger来“查看”您的视图框架。 - matt
感谢您的建议,@matt。请查看我更新的问题和我找到的答案。 - Vlad Z.
你实际上可以将它作为一个“答案”给出,而不是修改你的问题,并且两天后你可以接受你自己的答案。对于未来可能从你的工作中受益的其他人来说,那将是最有帮助的格式。 - matt
2个回答

15

支持iOS 10和Swift 3.0:

extension UINavigationBar {
    open override func sizeThatFits(_ size: CGSize) -> CGSize {
        let screenRect = UIScreen.main.bounds
        return CGSize(width: screenRect.size.width, height: 64)
    }
}

如何使用此扩展函数? - Hemang
@Hemang,将它放在空的Extensions.swift文件中(并将import UIKit作为第一行添加)到你的项目中。 - Deniss Fedotovs

12

我检查了接口调试器,看到以下情况(基本上它在尝试改变导航栏的高度,但它保持不变,并且只显示黑色空间 - 这是窗口颜色):

输入图像描述

后来我进行了更深入的调查,发现它没有调用“_UINavigationBarBackground”。

然后我检查了快速枚举的 view.classForCoder,并发现键已更改为“_UIBarBackground”,因此我更新了 layoutSubviews():

override func layoutSubviews() {
    super.layoutSubviews()

    let shift = TMNavigationBar.heightIncrease/2

    ///Move the background down for [shift] point
    let classNamesToReposition = isIOS10 ? ["_UIBarBackground"] : ["_UINavigationBarBackground"]

    for view: UIView in self.subviews {

        if classNamesToReposition.contains(NSStringFromClass(view.classForCoder)) {
            let bounds: CGRect = self.bounds
            var frame: CGRect = view.frame
            frame.origin.y = bounds.origin.y + shift - 20.0
            frame.size.height = bounds.size.height + 20.0
            view.frame = frame
        }
    }
}

干杯。


这对我不起作用。我按照您建议的确切步骤进行操作。我发现光标在上面的类中走了很多地方,但它从未调用override func sizeThatFits(size: CGSize) -> CGSize {...},所以我无法看到更新后的高度?有什么想法吗? - Hemang
我已经为此创建了一个gist,请看一眼。 - Hemang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接