UINavigationBar详细指南

2018-03-29  本文已影响212人  氮化镓加砷

1.UINavigationBar和UINavigationItem

UINavigationItem : NSObject

When building a navigation interface, each view controller pushed onto the 
navigation stack must have a `UINavigationItem` object that contains the 
buttons and views it wants displayed in the navigation bar. The 
managing UINavigationController object uses the navigation items of the 
topmost two view controllers to populate the navigation bar with content.

当view controller push进入navigation stack的时候,UINavigationItem是必须存在的,通常navigationController已经自动创建了UINavigationItem,它负责管理UInavigationController中的item和Title的内容以及交互。

UINavigationBar :UIView<UIBarPositioning>

A UINavigationBar object is a bar, typically displayed at the top of the 
window, containing buttons for navigating within a hierarchy of screens. 
The primary components are a left (back) button, a center title, and an 
optional right button. You can use a navigation bar as a standalone object or 
in conjunction with a navigation controller object.

A navigation bar is most commonly used within a navigation controller. 
The object creates, displays, and manages its 
associated navigation bar, and uses attributes of the view controllers you 
add to control the content displayed in the navigation bar.

If you use a navigation controller to manage the navigation between 
different screens of content, the navigation controller creates a navigation 
bar automatically and pushes and pops navigation items when appropriate.

图片.png

通常情况下我们使用UInavigationController push或者pop一个viewController的时候,UINavigationBar会被自动的创建,UINavigationBar是一个View的子类,我们可以自定义其显示的样式,包括title字体,背景,颜色等。

关系

A navigation controller uses the navigationItem property 
on UIViewController to provide the model objects to its navigation bar when 
navigating a stack of view controllers. The default navigation item uses the 
view controller’s title, but you can override the navigationItem on 
a UIViewController subclass to gain complete control 
of the navigation bar’s content.

UINavigationBar的内容通常是由navigationItem提供,包括title和items等,如果想自定义UINavigationBar中的内容,那么需要更改navigationItem的配置。

2.UINavigationBar

UIBarStyle默认有4中样式,translucent属性设置bar是否透明。
Bar默认带有毛玻璃效果。

typedef enum UIBarStyle : NSInteger {
    UIBarStyleDefault = 0,
    UIBarStyleBlack = 1,
    UIBarStyleBlackOpaque = 1,
    UIBarStyleBlackTranslucent = 2
} UIBarStyle;

UINavigationBar可以自定义的属性

Core Attributes : Style , Bar Tint , Shadow Image, Back Image, Back Mask.
Attribute: Title Font, Title Color, Title Shadow.

tip:去除UINavigationBar下方横线

[self.navigationBar setShadowImage:[[UIImage alloc] init]];
/* 全局 */
[[UINavigationBar appearance] setShadowImage:[[UIImage alloc] init]];
/* 另外一种方式 */
self.navigationController.navigationBar.clipsToBounds = YES; 

3.UINavigationItem

UINavigationItem提供了API设置leftItems,titleView,rightItems 和BackItems的方法。

3.1 backBarButtonItem

When this navigation item is immediately below the top item in the stack, 
the navigation controller derives the back button for the navigation bar from 
this navigation item. When this property is `nil`, the navigation item uses 
the value in its title property to create an appropriate back button. If you 
want to specify a custom image or title for the back button, you can assign a 
custom bar button item (with your custom title or image) to this property 
instead. When configuring your bar button item, do not assign a custom 
view to it; the navigation item ignores custom views in the back bar button 
anyway.

backBarButtonItem在UINavigationController中push时候自动的添加,如果你没有指定title,则返回按钮中的文字默认是前一个view controller的title。
不要尝试去添加custom view,因为不会生效。
hidesBackButton设置为YES可以隐藏返回按钮,默认是NO。

The backBarButtonItem property of a navigation item reflects the back 
button you want displayed when the current view controller is just below the 
topmost view controller. In other words, the back button is not used when 
the current view controller is topmost.

If the title of your back button is too long to fit in the available space on the 
navigation bar, the navigation bar may substitute the string “Back” in place 
of the button’s original title. The navigation bar does this only if the back 
button is provided by the previous view controller. If the new top-level view 
controller has a custom left bar button item—an object in the 
leftBarButtonItems or BarButtonItem property of its navigation item—the navigation bar does not change the button title.


你在当前View controller中设置的backBarButtonItem并不是当前view中backBarButtonItem的样式,而是从当前view controller中push出的view controller中backBarButtonItem的样式,topmost view controller中backBarButtonItem是无效的。
换而言之,当你准备push一个view controller并想自定义这个view controller的backBarButtonItem,那么在push之前,就需要设置好backBarButtonItem的样式。

UIViewController *nextViewController = [[UIViewController alloc] initWithNibName:@"" bundle:nil];
//设置nextViewController中navigationbar的backBtn样式。
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"navBacklIcon"] style:UIBarButtonItemStylePlain target:self action:@selector(Navback)];
[self showViewController:nextViewController sender:nil];

backBarButtonItem的title如果过长则会显示"back"。
如果设置了leftBarButtonItem,则backBarButtonItem将不会显示,除非将leftItemsSupplementBackButton设置为YES,默认为NO。
你可以用leftBarButtonItem替代backBarButtonItem,但是backBarButtonItem和leftBarButtonItem的位置是有差异的。

3.自定义UINavigationController

通常一个项目NavigationBar的风格都是统一的,我们可以通过下面方法来设置全局样式.

[[UINavigationBar appearance] setShadowImage:[[UIImage alloc] init]];
[[UINavigationBar appearance] set........

但是一个更好的方法是自定义一个UINavigationController。

@interface Q_navigationController ()<UINavigationControllerDelegate,UIGestureRecognizerDelegate>
@end

@implementation Q_navigationController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self configNavBar];
}
-(void)configNavBar{//全局样式
    [self.navigationBar setShadowImage:[[UIImage alloc] init]];
    self.navigationBar.translucent = NO;
    self.navigationBar.titleTextAttributes = @{NSFontAttributeName:[UIFont boldSystemFontOfSize:17],
                                               NSKernAttributeName:[NSNumber numberWithInteger:2],
                                               NSForegroundColorAttributeName:[UIColor colorWithRed:18.0/255 green:150.0/255 blue:219.0/255 alpha:1]
                                               };
    self.navigationBar.tintColor = [UIColor colorWithRed:18.0/255 green:150.0/255 blue:219.0/255 alpha:1];
}
@end

UINavigationControllerDelegate是UINavigationController的回调,我们可以在push和pop的时候收到回调,自定义一些需要的事情,比如设置自定义返回按钮。

-(void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
    if (navigationController.viewControllers.count > 1) {
        viewController.navigationItem.leftBarButtonItem = self.navBackBtn;
    }
}
-(UIBarButtonItem *)navBackBtn{
    if(!_navBackBtn){
        _navBackBtn =[[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"navBacklIcon"] style:UIBarButtonItemStylePlain target:self action:@selector(Navback)];
    }
    return _navBackBtn;
}

自定义的UINavigationController也会带来一些问题,比如边缘返回的手势失效了,为了能让它正常的工作,我们还需要做一些工作,在需要它的时候将其enabled设置为YES。

- (void)viewDidLoad {
    [super viewDidLoad];
    [self configNavBar];
    
    self.delegate = self;
    self.interactivePopGestureRecognizer.delegate = self;
}

-(void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
    if (navigationController.viewControllers.count <= 1) {
        self.interactivePopGestureRecognizer.enabled = NO;
    }else{
        self.interactivePopGestureRecognizer.enabled = YES;
    }
}

但是interactivePopGestureRecognizer可能会引入一些手势冲突问题,比如https://www.jianshu.com/p/ffde99688cff中描述的那样。

总结

理解UINavigationBar和UINavigationItem的关系,这让我们更加优雅的设计代码去配置项目中导航栏。

上一篇下一篇

猜你喜欢

热点阅读