iOS 11 大型标题更改事件

iOS 11 Large Title change event

我想在iOS 11 大标题变化时获取事件。即当用户滚动视图时将位置更改为导航栏。我已经检查了 UINavigationBar class 但我无法从中得到它。

我想要实现的屏幕设计就像当大标题可见时我想要透明的导航栏但是当标题向上滚动到导航栏时我想要纯色的导航栏。

通过scrollViewDidScroll函数获取UINavigationBar的当前高度即可。

func scrollViewDidScroll(_ scrollView: UIScrollView) {

    //Get current height of navigation bar when tableview/collectionview/scrollview did scroll
    guard let navBarHeight = navigationController?.navigationBar.frame.height else {
        return
    }

    //Compare with standard height of navigation bar.
    if navBarHeight > 44.0 {
        self.navigationController?.navigationBar.shadowImage = UIImage()
        self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
        self.navigationController?.navigationBar.barTintColor = .clear
    } else {
        self.navigationController?.navigationBar.shadowImage = nil
        self.navigationController?.navigationBar.setBackgroundImage(nil, for: .default)
        self.navigationController?.navigationBar.barTintColor = .green
    }
}

我已经在我的 UIViewController 的子类的 ViewWillAppear 中添加了这个观察者。并根据其高度设置颜色如下:

在视图中会出现:

UINavigationBar *navBar = self.navigationController.navigationBar;
[navBar addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew context:nil];

在视图中会消失:

UINavigationBar *navBar = self.navigationController.navigationBar;
[navBar removeObserver:self forKeyPath:@"frame" context:NULL];

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
if ([keyPath isEqualToString:@"frame"]) {
    [self setNavigationBarColour];;
}

}

- (void)setNavigationBarColour
{
    UINavigationBar *navBar = self.navigationController.navigationBar;
    CGFloat height = navBar.bounds.size.height;
    if(height>44)
    {
        [navBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
        [navBar setTranslucent:YES];
        [navBar setShadowImage:[UIImage new]];
    }
    else
    {
        [navBar setBackgroundImage:[[UINavigationBar appearance] backgroundImageForBarMetrics:UIBarMetricsDefault] forBarMetrics:UIBarMetricsDefault];
        [navBar setTranslucent:NO];
        [navBar setShadowImage:[[UINavigationBar appearance] shadowImage]];
    }
}

对 Piyush Hirpara 答案(关于性能)的一个小改进是将您的导航栏子类化,并且仅在 layoutSubviews 上更新:

class ObservingLargeTitleNavigationBar: UINavigationBar {

    override func layoutSubviews() {
        super.layoutSubviews()

        updateLargeTitle()
    }

    private func updateLargeTitle() {
        if #available(iOS 11.0, *) {
            if frame.height > 44 {
                // code logic when large title is visible
            } else {
                // code logic when large title is hidden
            }
        }
    }
}

请注意,在某些情况下可能需要调整 frame.height44 值。我在 60 有它,例如在 iPhone X.

的配置中