UINavigationBar with Large Titles - how to find extra height in iOS 11

无人久伴 提交于 2021-02-07 06:05:56

问题


When using prefersLargeTitles for a UINavigationController's UINavigationBar in iOS 11, the nav bar increases height. The increase is from 44 to 96 on the iPhones I have checked, but I think those numbers can change per device (or at least we need to code as if they can).

I want to programmatically find the 'extra' height - the height of the large titles area that is added beneath the traditional UINavigationBar when a large title is displayed. I can easily find the entire height of the bar with the large title displayed, but is there a way to programmatically find the height of the large title portion of the bar alone (without any hardcoding)?

The reason I need this is that there are times that I want to programmatically scroll to the top of a UITableView, pulling down the large title (which has scrolled up under the "regular height" nav bar) so that it is showing, and the content offset I need is the extra height of the nav bar. I could use the total height of the navigation bar, but this would pull the UITableView down too far. To do this now, I need to hardcode as below:

[self.tableView setContentOffset:CGPointMake(0, -52) animated:NO];

回答1:


I think you won't find a way to clearly resolve your problem. What you are asking for is a part of a navigation bar internals which is not exposed to the user. However, I think I can offer you a workaround.

To understand this let's take a look at the navigation bar (with large titles enabled) in the view debugger. As you can see on the below image there is an extra view containing the large title for a particular view controller. This view is not present when you don't support large titles.

Basically, what you want to know is the height of that view.

This is my proposed solution/workaround

extension UINavigationBar
{
    var largeTitleHeight: CGFloat {
        let maxSize = self.subviews
            .filter { $0.frame.origin.y > 0 }
            .max { $0.frame.origin.y < $1.frame.origin.y }
            .map { $0.frame.size }
        return maxSize?.height ?? 0
    }
}

What it does

  1. Filters out subviews which start on the top of the navigation bar. They are most probably a background or the navigation area, we don't need them.
  2. Finds the lowest subview in the in the navigation bar.
  3. Maps the resulted subview frame to the frame size.
  4. Returns the height of the found subview or 0 if none was found.

The obvious drawback of this approach is that it's tightly coupled to the structure of the navigation bar which may change in the future. However, it's unlikely that you will get something more than one or another dirty trick.

The result of the execution should look like follows.

print("Extra height: \(navigationController!.navigationBar.lagreTitleHeight)")
Extra height: 52.0



回答2:


As I understand it, you have your tableView origin under the navigationBar, at y = 0 in your UIViewController's view.

Your tableView should have its top bound fix to the top layout guide, or use the new safe area. That way you won't have to programmatically calculate what's the size of the navigationBar.

If you never used it, take a look at auto-layout.




回答3:


You can simply scroll to the top of the table view without knowing the size of the navigation bar. UITableView comes with an API for that.

Option 1

// Get the first index path. You might want to check here whether data source item exists.
NSIndexPath *firstIndexPath = [NSIndexPath indexPathForRow:0
                                                 inSection:0];
// Scroll to it. You can play with scroll position to get what you want
[tableView scrollToRowAtIndexPath:firstIndexPath
                 atScrollPosition:UITableViewScrollPositionTop
                         animated:YES];

Option 2

CGPoint offset = CGPointMake(0.0, -tableView.contentInset.top);
[tableView setContentOffset:offset animated:YES];



回答4:


I just experienced this same issue.

 -(void)layoutSubviews{
            [super layoutSubviews];
            CGRect rectStatusBar = [[UIApplication sharedApplication] statusBarFrame];
            if (rectStatusBar.size.height==44.f) {
               //statusBar shows
            }else{
                if (@available(iOS 11.0, *)) {
                    for ( UIView*view in self.subviews) {
                        if ([NSStringFromClass(view.classForCoder) isEqualToString:@"_UINavigationBarContentView"]) {
                            view.frame = CGRectMake( 0,20,view.frame.size.width,44);
                        }
                        else if ([NSStringFromClass(view.classForCoder) isEqualToString:@"_UIBarBackground"]) {
                            view.frame = CGRectMake(0,0,view.frame.size.width, 64);
                        }
                    }
                }
            }
        }


来源:https://stackoverflow.com/questions/46821623/uinavigationbar-with-large-titles-how-to-find-extra-height-in-ios-11

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!