前言
这里有极其重要的一个细节,在当前控制器里打印:
// 它们是同一个 navigationItem !!! 即 navigationBar 的 items 中的第一个 navItem 是控制器的 navItem
NSLog(@"%@", self.navigationController.navigationBar.items[0]);
NSLog(@"%@", self.navigationItem);
通过上一节的 UINavigationBar 的学习,知道了 UINavigationItem 是可以在 navigationBar 上 push 和 pop 上操作的,之前对 UINavigationItem 的使用仅仅限于控制器的 navigationItem 属性。尴尬...(觉得应该把标题改成 “UI开发中容易被我忽略的细节之...”)
目录
-
- UINavigationItem 的属性和方法
一、UINavigationItem 的属性和方法:
首先 UINavigationItem 是继承自 NSObject
的,在之前的印象中一致把它作为视图使用,以为至少也应该是继承自 UIView 的吧,之前的自以为完全错误!(UINavigationController 继承自 UIViewController,UINavigationBar 继承自 UIView
)
NS_CLASS_AVAILABLE_IOS(2_0) @interface UINavigationItem : NSObject
// iOS 11 后出现的,largeTitle 的显示 mode 枚举
typedef NS_ENUM(NSInteger, UINavigationItemLargeTitleDisplayMode) {
/// Automatically use the large out-of-line title based on the state of the previous item in the navigation bar. An item with largeTitleDisplayMode=Automatic will show or hide the large title based on the request of the previous navigation item. If the first item pushed is set to Automatic, then it will show the large title if the navigation bar has prefersLargeTitles=YES.
UINavigationItemLargeTitleDisplayModeAutomatic,
/// Always use a larger title when this item is top most.
UINavigationItemLargeTitleDisplayModeAlways,
/// Never use a larger title when this item is top most.
UINavigationItemLargeTitleDisplayModeNever,
} NS_SWIFT_NAME(UINavigationItem.LargeTitleDisplayMode);
// 指定初始化方法
- (instancetype)initWithTitle:(NSString *)title NS_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;
// 在堆栈最顶部的标题,默认是 nil
@property(nullable, nonatomic,copy) NSString *title;
// 用来代替上面 title 的自定义 View,水平大小,当 item 在堆栈顶的时候使用
// frame 默认居中
@property(nullable, nonatomic,strong) UIView *titleView;
// 在 title 上方显示的文字,navigationBar 会变宽
@property(nullable,nonatomic,copy) NSString *prompt __TVOS_PROHIBITED;
如果 topItem 设置了 prompt,而 backItem 没有设置 prompt,则点击 topItem 左侧的返回按钮不能 pop
prompt.gif
// 定义子 navigationItem 的左侧的返回按钮,即做 push 操作后,topItem 左边的返回按钮
@property(nullable,nonatomic,strong) UIBarButtonItem *backBarButtonItem __TVOS_PROHIBITED;
// navigationItem 隐藏自己左边的返回按钮
// 和 backBarButtonItem 不同,hidesBackButton 是对自己左边返回按钮起作用,而 backBarButtonItem 设置的是 push 出现的 navigationItem 左边的返回按钮
@property(nonatomic,assign) BOOL hidesBackButton __TVOS_PROHIBITED
// 动画隐藏
- (void)setHidesBackButton:(BOOL)hidesBackButton animated:(BOOL)animated __TVOS_PROHIBITED;
// iOS 5 之后出现的,设置左右两边的 Item 的组
// 这里有一个很有意思的点,如果把一个 BarButtonItem 放在数组里面设置为 leftBarButtonItems 或 rightBarButtonItems,这时候在把这个 BarButtonItem 设置为 leftBarButtonItem 或 rightBarButtonItem 是无效的
@property(nullable,nonatomic,copy) NSArray *leftBarButtonItems NS_AVAILABLE_IOS(5_0);
@property(nullable,nonatomic,copy) NSArray *rightBarButtonItems NS_AVAILABLE_IOS(5_0);
- (void)setLeftBarButtonItems:(nullable NSArray *)items animated:(BOOL)animated NS_AVAILABLE_IOS(5_0);
- (void)setRightBarButtonItems:(nullable NSArray *)items animated:(BOOL)animated NS_AVAILABLE_IOS(5_0);
// iOS 5 之后出现的,设置 topItem 的 leftBarButtonItems 或 leftBarButtonItem 时,backBarButtonItem 会自动隐藏
// 设置该属性为 YES,则可以同时显示 backBarButtonItem
@property(nonatomic) BOOL leftItemsSupplementBackButton NS_AVAILABLE_IOS(5_0) __TVOS_PROHIBITED;
// 给 navigationItem 添加左右按钮
// 设置 leftItemsSupplementBackButton 为 YES,才能使 leftBarButtonItem 和 backBarButtonItem 同时显示
@property(nullable, nonatomic,strong) UIBarButtonItem *leftBarButtonItem;
@property(nullable, nonatomic,strong) UIBarButtonItem *rightBarButtonItem;
- (void)setLeftBarButtonItem:(nullable UIBarButtonItem *)item animated:(BOOL)animated;
- (void)setRightBarButtonItem:(nullable UIBarButtonItem *)item animated:(BOOL)animated;
// iOS 11 后出现的,当 navigationBar 的 prefersLargeTitles 设置为 YES 时,即有 largeTitle 显示时,largeTitleDisplayMode 用来设置其显示样式
@property (nonatomic, readwrite, assign) UINavigationItemLargeTitleDisplayMode largeTitleDisplayMode API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(tvos);
// iOS 11 后出现的,在导航条上添加搜索框,且导航条自动变宽
@property (nonatomic, retain, nullable) UISearchController *searchController API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(tvos);
// iOS 11 后出现的,默认为 YES,topViewController 是 tableViewController 是,滚动 tableView 隐藏 searchBar
@property (nonatomic) BOOL hidesSearchBarWhenScrolling API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(tvos);
至此 navigationItem.h 看完了,平时我们用的最多是 leftBarButtonItem、rightBarButtonItem 和 backBarButtonItem,大家都比较熟悉了,leftItemsSupplementBackButton 需要注意一下,设置为 YES ,保证 backBarButtonItem 正常显示。
另外是 iOS 11 后添加的几个属性,应该了解一下。
这里有很重要的一点,连着上一节的 navigationBar 的那部分思考一下,为什么 navigationBar 能 push 和 pop navigationItem 呢,且方式什么的和导航条 push 和 pop 子控制器一样。其实我们在导航堆栈里面的 push 和 pop 操作的时候,nvigationBar 的 nvaigationItem 堆栈里面也在跟着 push 和 pop,直白一点说,就是我们 push 到新控制器的时候,新控制器也会新建 navigationItem 并添加到 navigationBar 的 Items 里面去。
// 在当前控制打印下面两句,输出是一样的:
NSLog(@"%@", self.navigationController.navigationBar.topItem);
NSLog(@"%@", self.navigationItem);
end