说明:在Demo中Windows的根控制器为UINavigationController,修改其View背景色为深蓝色,其根控制器为背景色为浅蓝色的FirstViewController,NEXT按钮push进下一个UIViewController。
UINavigationController的ToolBar默认隐藏,在FirstViewController中设置不隐藏。
UINavigationController结构解析
- UINavigationController view结构
- UINavigationController栈结构
UINavigationController通过push/pop方法进行转场,这就意味着UINavigationController管理的view controller 是栈结构的(LIFO--先进后出)。如图所示viewControllers数组就是当前被推进栈的view controller组成的数组
// UINavigationController的两个属性
@property(nonatomic,copy) NSArray<__kindof UIViewController *> *viewControllers; // 当前在栈中view controller
@property(nullable, nonatomic,readonly,strong) UIViewController *topViewController; // 在栈顶的view controller
UINavigationController问题
下面通过几个问题来补充说明UIViewController的其他内容
1.topViewController的视图是如何布局的?
UIRectEdgeAll.png从上图我们可以观察到FirstViewController及UINavigationController的topViewController的大小和UINavigation的view(深蓝色部分)是一样,有时候我们又希望topViewController不要被NavigationBar和ToolBar覆盖,这个时候我们应该怎么设置呢?
@property(nonatomic,assign) UIRectEdge edgesForExtendedLayout NS_AVAILABLE_IOS(7_0); // Defaults to UIRectEdgeAll
@property(nonatomic,assign) BOOL extendedLayoutIncludesOpaqueBars NS_AVAILABLE_IOS(7_0); // Defaults to NO, but bars are translucent by default on 7_0.
UIViewController有如上两个属性,其中edgesForExtendedLayout为UIRectEdge类型
typedef NS_OPTIONS(NSUInteger, UIRectEdge) {
UIRectEdgeNone = 0,
UIRectEdgeTop = 1 << 0,
UIRectEdgeLeft = 1 << 1,
UIRectEdgeBottom = 1 << 2,
UIRectEdgeRight = 1 << 3,
UIRectEdgeAll = UIRectEdgeTop | UIRectEdgeLeft | UIRectEdgeBottom | UIRectEdgeRight
} NS_ENUM_AVAILABLE_IOS(7_0);
当extendedLayoutIncludesOpaqueBars为默认的NO且navigationBar和ToolBar均为半透明效果时设置edgesForExtendedLayout效果如下所示
UIRectEdgeAll.png UIRectEdgeNone.png UIRectEdgeTop.png UIRectEdgeBottom.png这时候如果设置NavigationController的NavigationBar和ToolBar为不透明效果
[self.navigationController.navigationBar setTranslucent:NO];
[self.navigationController.toolbar setTranslucent:NO];
在extendedLayoutIncludesOpaqueBars为默认的NO情况下设置edgesForExtendedLayout为UIRectEdgeAll,效果如图所示
self.edgesForExtendedLayout = UIRectEdgeAll;
[self.navigationController.navigationBar setTranslucent:NO];
[self.navigationController.toolbar setTranslucent:NO];
[self setExtendedLayoutIncludesOpaqueBars:NO];
Bar不半透明_UIRectEdgeAll_setExtendedLayoutIncludesOpaqueBars = NO.png
这个时候如果想将FirstViewController布局到bar上面去,只需要设置ExtendedLayoutIncludesOpaqueBars(延伸到不透明区域)为YES即可
self.edgesForExtendedLayout = UIRectEdgeAll;
[self.navigationController.navigationBar setTranslucent:NO];
[self.navigationController.toolbar setTranslucent:NO];
[self setExtendedLayoutIncludesOpaqueBars:YES];
ExtendedLayoutIncludesOpaqueBars == YES.png
总结:edgesForExtendedLayout控制topViewController在UINavigationController上的布局,extendedLayoutIncludesOpaqueBars为YES时可延伸到不透明区域([bar setTranslucent:NO]来设置为不透明)
// 所以通过以下几个属性就可以设置topViewController在UINavigationController上的布局了
self.edgesForExtendedLayout = UIRectEdgeAll;
[self.navigationController.navigationBar setTranslucent:NO];
[self.navigationController.toolbar setTranslucent:NO];
[self setExtendedLayoutIncludesOpaqueBars:YES];
2.UINavigationController有多个view controller却只有一个navigationBar,怎么针对不同的view controller展示不同的顶栏
Nav栈结构.jpg说明:UINavigationController由viewControllers、navigationBar、toolBar组成,其中navigationBar中有一个items属性的数组存放UINavigationItem数据,与UINavigationController中的viewControllers一一对应。也是栈结构的。在UINavigationItem中有title、titleView等属性,不同的viewController持有不同的UINavigationItem,通过设置UINavigationItem的属性可实现一个navigationBar为不同的viewController展示不同的顶栏的效果啦。
未完待续...
网友评论