目录
1. UINavigationController
2. UITabBarController
前言
建议不要使用系统的导航栏。
思想:
创建UIViewContrller基类,在该类中创建自定义View作为导航栏。
1. UINavigationController
- 自定义UINavigationController子类
以下文件(并不是最终的文件)中的功能选择性使用,仅为了说明功能
YTNavBarController.h
#import
@interface YTNavBarController : UINavigationController
@end
YTNavBarController.m
#import "YTNavBarController.h"
#import "YTTabBarController.h"
@interface YTNavBarController ()
@end
@implementation YTNavBarController
/**
* 第一次使用这个类的时候会调用(1个类只会调用1次)
*/
+ (void)initialize{
// 设置导航栏主题
[self setupNavBarTheme];
}
/**
* 设置导航栏主题
*/
+ (void)setupNavBarTheme{
// 获取导航栏单例
UINavigationBar *navBar = [UINavigationBar appearance];
背景色、背景图片、填充色
// 设置导航栏 背景色
navBar.barTintColor=YTMainColor;
// 设置导航栏 背景图片(和背景色二选一)
[navBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
// 设置导航栏 文本填充色
[navBar setTintColor:[UIColor whiteColor]];
是否半透明
// 设置导航栏 是否半透明
// 默认:true,以屏幕左上角为坐标原点。false则从导航栏左下角为坐标原点。
navBar.translucent=false;
返回文本位置、标题样式、自定义返回按钮图片
// 隐藏导航栏 返回按钮文字(移到屏幕外)
[[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -60)
forBarMetrics:UIBarMetricsDefault];
// 设置导航栏 标题
[navBar setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor whiteColor],NSFontAttributeName:YTFONT_PF(18)}];
// 设置导航栏 返回按钮
[navBar setBackIndicatorImage:[UIImage imageNamed:@"backNavT"]];
[navBar setBackIndicatorTransitionMaskImage:[UIImage imageNamed:@"backNavT"]];
黑白风格、下方黑线
// 设置导航栏 风格
[navBar setBarStyle:UIBarStyleDefault]; // 默认(白色背景、黑色文字、状态栏文字黑色) ,UIBarStyleBlack(黑色背景、白色文字,状态栏文字白色) 发生冲突时优先级低
// 去除导航栏下方的黑线
[[UINavigationBar appearance] setShadowImage:[UIImage new]];
/*
navigationItem (在push前不要设,此时还不在push栈中,所以无效)
// 设置导航栏 标题文本
self.navigationItem.title=@"";
// 设置导航栏 标题视图
self.navigationItem.titleView=[UIView new];
// 设置导航栏 返回项
self.navigationItem.backBarButtonItem=[[UIBarButtonItem alloc]initWithCustomView:[UIView new]];
// 设置导航栏 返回项标题属性
[self.navigationItem.backBarButtonItem setTitleTextAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:18]} forState:UIControlStateNormal];
// 设置导航栏 右侧项
self.navigationItem.rightBarButtonItem=[[UIBarButtonItem alloc]initWithCustomView:[UIView new]];
*/
}
- (void)viewDidLoad{
[super viewDidLoad];
设置dele
[self setDelegate:self];
禁用侧滑手势
[self.interactivePopGestureRecognizer setEnabled:false];
侧滑手势dele:self
self.interactivePopGestureRecognizer.delegate = self;
}
/**
* 状态栏文字颜色 白色
*/
-(UIStatusBarStyle)preferredStatusBarStyle{
return UIStatusBarStyleLightContent;
}
/*
以下是 隐藏、显示系统Tabbar
// 重写以下方法(隐藏系统Tabbar)
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated{
if(self.viewControllers.count>=1){
viewController.hidesBottomBarWhenPushed = YES;
}
[super pushViewController:viewController animated:animated];
}
*/
/*
以下是 隐藏、显示自定义Tabbar
// 重写以下方法(隐藏自定义Tabbar)
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated{
if(self.viewControllers.count>=1){
UIView *barView=((YTCustomTabbarViewController *)self.tabBarController).barView;
[UIView animateWithDuration:0.125 animations:^{
[barView setTransform:CGAffineTransformMakeTranslation(0, barView.frame.size.height)];
}];
}
[super pushViewController:viewController animated:animated];
}
#pragma mark < UINavigationControllerDelegate >
// 显示自定义Tabbar
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
if(viewController==navigationController.viewControllers[0]){
UIView *barView=((YTCustomTabbarViewController *)self.tabBarController).barView;
[UIView animateWithDuration:0.125 animations:^{
[barView setTransform:CGAffineTransformIdentity];
}];
}
}
*/
@end
- 相关概念
UINavigationController : UIViewController
由
UINavigationBar(顶部—公共导航条)
UIToolBar(底部—默认隐藏)
viewControllers(栈,栈顶则是当前显示的页)
组成
UINavigationBar 顶部—公共导航条
获取navBar(只读)
// 方式一
UINavigationBar *navBar=[UINavigationBar appearance];
// 方式二
UINavigationBar *navBar=self.navigationController.navigationBar;
标题、返回标题、返回图片
// TitleTextAttributes标题属性
[navBar setTitleTextAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:16],NSForegroundColorAttributeName:[UIColor redColor]}];
// 隐藏返回标题(移到界面外)
[[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -60) forBarMetrics:UIBarMetricsDefault];
// 设置返回按钮图标
[navBar setBackIndicatorImage:[UIImage imageNamed:@""]];
[navBar setBackIndicatorTransitionMaskImage:[UIImage imageNamed:@""]];
外观
// 设置/获取 是否隐藏navBar
[navBar setHidden:true];
[self.navigationController setNavigationBarHidden:true];
[self.navigationController setNavigationBarHidden:true animated:true];
BOOL navigationBarHidden=self.navigationController.navigationBarHidden;
// barStyle
[navBar setBarStyle:UIBarStyleBlack];
/*
UIBarStyleDefault
UIBarStyleBlack
*/
// bgColor
[navBar setBackgroundColor:[UIColor redColor]];
// bgImg([UIImage new] 则透明)
[navBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
// barTintColor
[navBar setBarTintColor:[UIColor redColor]];
// tinColor(项填充色 如文本)
[navBar setTintColor:[UIColor redColor]];
// translucent(默认:true,false则坐标左上角为NavBar下方)
[navBar setTranslucent:true];
// alpha
[navBar setAlpha:0];
UINavigationItem (用于VC,仅影响本页面)
获取当前页的navItem
UINavigationItem *navItem=self.navigationItem;
// 无效
self.navigationController.navigationItem
标题
// 标题
[self.navigationItem setTitle:@"标题"];
// 自定义标题View
[self.navigationItem setTitleView:[UIView new]];
左右项
// 获取左项(右项则right)
self.navigationItem.leftBarButtonItem
self.navigationItem.leftBarButtonItems
// 设置左项(从左到右,右项时从右到左)
[self.navigationItem setLeftBarButtonItem:[UIBarButtonItem new]];
[self.navigationItem setLeftBarButtonItems:@[[UIBarButtonItem new]]];
[self.navigationItem setLeftBarButtonItem:[UIBarButtonItem new] animated:true];
[self.navigationItem setLeftBarButtonItems:@[[UIBarButtonItem new]] animated:true];
// 设置点击事件(覆盖之前设置的方法)
[self.navigationItem.leftBarButtonItem setAction:@selector(handleButton:)];
返回项
// 获取/设置返回项是否隐藏
self.navigationItem.hidesBackButton;
[self.navigationItem setHidesBackButton:true];
[self.navigationItem setHidesBackButton:true animated:true];
// 设置返回项
[self.navigationItem setBackBarButtonItem:[UIBarButtonItem new]];
// 是否同时显示返回项和左项(返回项在左)
[self.navigationItem setLeftItemsSupplementBackButton:true];
UIToolBar(底部工具栏---默认隐藏,一般不用)
// 获取toolBar
UIToolbar *toolBar=self.navigationController.toolbar;
// 获取/设置 ToolBar是否隐藏(默认:是)
self.navigationController.isToolbarHidden
[self.navigationController setToolbarHidden:false];
[self.navigationController setToolbarHidden:true animated:true];
// barStyle
[toolBar setBarStyle:UIBarStyleBlack];
// translucent
[toolBar setTranslucent:true];
// tintColor项填充色
[toolBar setTintColor:[UIColor redColor]];
// bgImg
[toolBar setBackgroundImage:[UIImage new] forToolbarPosition:UIBarPositionTop barMetrics:UIBarMetricsDefault];
// bgColor
[toolBar setBackgroundColor:[UIColor blueColor]];
// 获取/设置子项
self.toolbarItems
self.toolbarItems=@[[UIBarButtonItem new]];
UIBarButtonItem(用于NavBar、ToolBar)
// 不是button的子类(和button很像),常用创建方式4种:
// 方式一:自定义View
UIBarButtonItem *barItem=[[UIBarButtonItem alloc]initWithCustomView:[UIView new]];
// 方式二:图片
UIBarButtonItem *barItem=[[UIBarButtonItem alloc]initWithImage:[[UIImage new]imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] style:UIBarButtonItemStylePlain target:self action:@selector(handleButtonItem:)];
// 方式三:标题
UIBarButtonItem *barItem=[[UIBarButtonItem alloc]initWithTitle:@"title" style:UIBarButtonItemStylePlain target:self action:@selector(handleButtonItem:)];
// 方式四:系统类型
// Done/Cancel/Edit/Save/Add/Bookmarks/Search/Refresh/Stop/Camera/Trash/Play/Pause/Rewind/FastForward/Compose/Organize/Reply/Action/FlexibleSpace(弹性间隔)/FixedSpace(设置间隔:bItem.width=50)
UIBarButtonItem *barItem=[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(handleSystemButton:)];
常用
UINavigationController *navC=[[UINavigationController alloc]initWithRootViewController:[UIViewController new]];
// 栈顶VC(readOnly)
UIViewController *topViewController=self.navigationController.topViewController;
// 当前显示VC(readOnly)
// 不一定是栈顶VC,如[栈顶VC presentV:VC]
UIViewController *visibleViewController=self.navigationController.visibleViewController;
// 设置/获取 viewControlers
[self.navigationController setViewControllers:@[[UIViewController new]] animated:true];
[self.navigationController setViewControllers:@[[UIViewController new]]];
NSArray *viewControllers=self.navigationController.viewControllers;
// 动态改变navBar的透明度
// navBar的bgImgV
UIImageView *bgImgV=self.navigationController.navigationBar.subviews.firstObject;
[bgImgV setAlpha:0.5];
VC拦截返回事件
- (void)viewWillDisappear:(BOOL)animated{
if ([self.navigationController.viewControllers indexOfObject:self]==NSNotFound) {
NSLog(@"clicked navigationbar back button");
}
}
跳转
跳到新页(2种)
// 方式一
[self.navigationController pushViewController:[UIViewController new] animated:true];
// 方式二
[self.navigationController showViewController:[UIViewController new] sender:nil];
返回到前页(3种)
// 一:返回到上一页
[self.navigationController popViewControllerAnimated:true];
// 二:返回到根视图页
[self.navigationController popToRootViewControllerAnimated:true];
// 三:返回到指定页
[self.navigationController popToViewController:self.navigationController.viewControllers[0] animated:true];
dele
self.navigationController.delegate=self;
// 即将显示VC时调用
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{}
// 显示VC后调用
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated{}
//
- (UIInterfaceOrientationMask)navigationControllerSupportedInterfaceOrientations:(UINavigationController *)navigationController{}
//
- (UIInterfaceOrientation)navigationControllerPreferredInterfaceOrientationForPresentation:(UINavigationController *)navigationController{}
//
- (nullable id )navigationController:(UINavigationController *)navigationController interactionControllerForAnimationController:(id ) animationController{
}
//
- (nullable id )navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC{
}
每个模块颜色不一
0.
YTNavBarController 中不设置统一背景色
1.
每个模块使用不同的UINavigationController(YTNavBarSubOneController、YTNavBarSubTwoController)
-(void)viewDidLoad{
[super viewDidLoad];
[self.navigationBar setBarTintColor:YTRGBColor(65 ,150 ,160)];
}
导航栏切换
原始方法 在VC的viewWillAppear方法中设置相应样式
缺点:交互太突兀,侧滑问题
情境一 无导航栏和有导航切换
隐藏和重新展示navBar
viewWillAppear
[self.navigationController setNavigationBarHidden:true animated:animated];
viewWillDisappear
[self.navigationController setNavigationBarHidden:false animated:true];
情景二 不同样式导航栏切换
方法一:
隐藏导航栏 + 自定义NavigationBar(侧滑失效:重新设置侧滑dele)
[self.navigationController setNavigationBarHidden:true animated:animated];
方法二:
侧滑动画
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
//
[self.transitionCoordinator animateAlongsideTransitionInView:self.view animation:^(id _Nonnull context) {
//
self.navigationController.navigationBar.alpha=1.0;
} completion:^(id _Nonnull context) {
}];
}
全屏侧滑(在任何地方都可以,非屏幕左侧)
:UINavigationController
-(void)viewDidLoad{
// 禁用系统的全屏侧滑,使用自定义滑动手势
UIGestureRecognizer *gesture=self.interactivePopGestureRecognizer;
gesture.enabled=false;
UIPanGestureRecognizer *panG=[[UIPanGestureRecognizer alloc]initWithTarget:gesture.delegate action:@selector(handleNavigationTransition:)];
[panG setDelegate:self];
[gesture.view addGestureRecognizer:panG];
}
-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
if(self.childViewControllers.count>1){
return true;
}
return false;
}
2. UITabBarController
为了高度自定义菜单栏样式,需要使用自定义的UITabBarController
- 使用系统UITabBarItem
YTCusTabBarViewController.h
#import
@interface YTCusTabBarViewController : UITabBarController
@end
YTCusTabBarViewController.m
#import "YTCusTabBarViewController.h"
#import "YTVoiceViewController.h"
#import "YTPersonModel.h"
#import "YTPersonModelTool.h"
#import "YTRealNameViewController.h"
@interface YTCusTabBarViewController ()
@end
@implementation YTCusTabBarViewController
+(void)initialize{
// 状态栏项(统一设置)
UITabBarItem *barItem=[UITabBarItem appearance];
// 状态栏项 文字的默认/选中颜色
[barItem setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor grayColor]} forState:UIControlStateNormal];
[barItem setTitleTextAttributes:@{NSForegroundColorAttributeName:YTMainColor} forState:UIControlStateSelected];
}
- (void)viewDidLoad {
[super viewDidLoad];
//
NSArray *contentArr=@[@[@"首页",@"home",@"homeS",@"YTHomeViewController"],@[@"消息",@"message",@"messageS",@"YTMessageViewController"],@[@"进度",@"processNS",@"processS",@"YTSpeedViewController"],@[@"我的",@"my",@"myS",@"YTMyViewController"]];
for(int i=0;i
iOS13需要适配(否则push后,选中颜色会变成蓝色)
UITabBarItem *tabbar=[UITabBarItem appearance];
if (@available(iOS 13.0, *)){
[self.tabBar setTintColor:[UIColor text_blackColor]];
[self.tabBar setUnselectedItemTintColor:[UIColor text_grayColor]];
}
[tabbar setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIColor text_grayColor], NSForegroundColorAttributeName, kFontMedium(10), NSFontAttributeName, nil] forState:UIControlStateNormal];
[tabbar setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIColor text_blackColor], NSForegroundColorAttributeName, kFontMedium(10), NSFontAttributeName, nil] forState:UIControlStateSelected];
- 使用自定义View
YTCustomTabbarViewController.h
#import
@interface YTCustomTabbarViewController : UITabBarController
@property (nonatomic,weak) UIView *barView;
@end
YTCustomTabbarViewController.m
#import "YTCustomTabbarViewController.h"
#import "YTHomeViewController.h"
#import "YTMyViewController.h"
#import "YTMessageViewController.h"
#import "YTSpeedViewController.h"
@interface YTCustomTabbarViewController ()
@property (nonatomic,weak) UIButton *selectButton;
@property (nonatomic,copy) NSArray *contentArr;
@property (nonatomic,weak) UILabel *tsL;
@end
@implementation YTCustomTabbarViewController
-(void)viewDidLoad{
[super viewDidLoad];
//
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(comeNewMessage:) name:ComeNewMessage object:nil];
//
CGRect barRect=self.tabBar.frame;
UIView *barView=[UIView new];
_barView=barView;
[barView setFrame:barRect];
[barView setBackgroundColor:[UIColor whiteColor]];
[self.view addSubview:barView];
//
_contentArr=@[@[@"首页",@"home",@"homeS",@"YTHomeViewController"],@[@"消息",@"message",@"messageS",@"YTMessageViewController"],@[@"进度",@"processNS",@"processS",@"YTSpeedViewController"],@[@"我的",@"my",@"myS",@"YTMyViewController"]];
//
CGFloat width=barView.frame.size.width/_contentArr.count;
CGFloat height=barView.frame.size.height;
for(int i=0;i<_contentArr.count;i++){
//
UIButton *itemButton=[UIButton new];
[itemButton setTag:500+i];
[itemButton addTarget:self action:@selector(handleButton:) forControlEvents:UIControlEventTouchUpInside];
[barView addSubview:itemButton];
[itemButton setFrame:CGRectMake(width*i, 0, width, height)];
//
UIImageView *iconImgV=[UIImageView new];
[iconImgV setTag:200+i];
[itemButton addSubview:iconImgV];
[iconImgV setImage:YTGetImage(_contentArr[i][1])];
[iconImgV autoAlignAxisToSuperviewAxis:ALAxisVertical];
[iconImgV autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:5];
//
UILabel *titleL=[UILabel new];
[titleL setTag:300+i];
[titleL setText:_contentArr[i][0]];
[titleL setTextColor:YTRGBColor(80, 80, 80)];
[titleL setFont:YTFONT_PF(11)];
[titleL setTextAlignment:NSTextAlignmentCenter];
[itemButton addSubview:titleL];
[titleL autoPinEdgeToSuperviewEdge:ALEdgeLeft withInset:0];
[titleL autoPinEdgeToSuperviewEdge:ALEdgeRight withInset:0];
[titleL autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:2];
if(i==1){
UILabel *tsL=[UILabel new];
_tsL=tsL;
[tsL setBackgroundColor:[UIColor redColor]];
[tsL setFont:YTFONT_PF(12)];
[tsL setTextAlignment:NSTextAlignmentCenter];
[tsL.layer setCornerRadius:10];
[tsL setTextColor:[UIColor whiteColor]];
[tsL.layer setMasksToBounds:true];
[itemButton addSubview:tsL];
[tsL autoPinEdgeToSuperviewEdge:ALEdgeRight withInset:20];
[tsL autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:0];
[tsL autoSetDimension:ALDimensionWidth toSize:20];
[tsL autoSetDimension:ALDimensionHeight toSize:20];
NSNumber *num=YTUserDefaultsObject(NO_READ_COUNT);
if([num intValue]>0){
[tsL setText:[NSString stringWithFormat:@"%@",YTUserDefaultsObject(NO_READ_COUNT)]];
[tsL setHidden:false];
}else{
[tsL setHidden:true];
}
}
//
if(i==0){
_selectButton=itemButton;
[titleL setTextColor:YTMainColor];
[iconImgV setImage:YTGetImage(_contentArr[i][2])];
}
//
[self addChildViewController:[[YTNavController alloc]initWithRootViewController:[NSClassFromString(_contentArr[i][3]) new]]];
}
}
//
-(void)handleButton:(UIButton *)button{
//
if(button!=_selectButton){
UIImageView *iconImgV=[self.view viewWithTag:_selectButton.tag-300];
[iconImgV setImage:YTGetImage(_contentArr[_selectButton.tag-500][1])];
UILabel *titleL=[self.view viewWithTag:_selectButton.tag-200];
[titleL setTextColor:YTRGBColor(80, 80, 80)];
_selectButton=button;
UIImageView *iconImgTV=[self.view viewWithTag:_selectButton.tag-300];
[iconImgTV setImage:YTGetImage(_contentArr[_selectButton.tag-500][2])];
UILabel *titleTL=[self.view viewWithTag:_selectButton.tag-200];
[titleTL setTextColor:YTMainColor];
self.selectedIndex=button.tag-500;
if(button.tag-500==1){
[_tsL setHidden:true];
YTUserDefaultsSave(@(0), NO_READ_COUNT)
[UIApplication sharedApplication].applicationIconBadgeNumber = -1;
}
}
}
-(void)dealloc{
[[NSNotificationCenter defaultCenter]removeObserver:self];
}
-(void)comeNewMessage:(NSNotification *)noti{
//
NSNumber *num=YTUserDefaultsObject(NO_READ_COUNT);
[_tsL setText:[NSString stringWithFormat:@"%@",num]];
[_tsL setHidden:false];
}
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
// 删除系统自动生成的UITabBarButton
[self.tabBar removeFromSuperview];
}
@end
- 相关概念
其他
// VCs
[self setViewControllers:@[]];
// 填充色
[self.tabBar setTintColor:kbuttongroundColor];
// 半透明
[self.tabBar setTranslucent:true];
dele
// dele
[self.tabBar setDelegate:self];
// 是否允许选中
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController{
return true;
}
// 选中后调用
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController{
}
//
-(void)tabBarController:(UITabBarController *)tabBarController willBeginCustomizingViewControllers:(NSArray<__kindof UIViewController *> *)viewControllers{}
//
- (void)tabBarController:(UITabBarController *)tabBarController willEndCustomizingViewControllers:(NSArray<__kindof UIViewController *> *)viewControllers changed:(BOOL)changed{}
//
- (void)tabBarController:(UITabBarController *)tabBarController didEndCustomizingViewControllers:(NSArray<__kindof UIViewController *> *)viewControllers changed:(BOOL)changed{}
//
- (UIInterfaceOrientationMask)tabBarControllerSupportedInterfaceOrientations:(UITabBarController *)tabBarController{}
//
- (UIInterfaceOrientation)tabBarControllerPreferredInterfaceOrientationForPresentation:(UITabBarController *)tabBarController{}
//
-(id)tabBarController:(UITabBarController *)tabBarController interactionControllerForAnimationController:(id)animationController{}
//
- (nullable id )tabBarController:(UITabBarController *)tabBarController
animationControllerForTransitionFromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC{}
*/