iOS小技能:自定义导航栏,设置全局导航条外观

5,311 阅读3分钟

这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战

前言

在开发需求时app中使用的导航条在一个模块的主题基本是一致的,因此可通过自定义导航条来进行统一控制。

  • 设置导航条渐变颜色
  • 设置全局导航条按钮主题
  • 拦截push:通过自定义类,重写自带的方法实现

I、自定义导航栏

1.1 HWNavigationController.h

#import <UIKit/UIKit.h>
#import "UIBarButtonItem+Extension.h"
#import "ImageTools.h"

@interface HWNavigationController : UINavigationController

+ (void) setttingAppearance;

- (void)setupNavigationBarBarStyle:(NSInteger)barStyle;
#pragma mark - ******** 设置列表控制器的样式
+ (void)setupListnavigationItemAndBarStyle:(UIViewController*)vc;
+ (void)setupDetailnavigationItemAndBarStyle:(UIViewController*)vc;
@end

1.2 设置全局导航条按钮主题

setttingAppearance

#import "HWNavigationController.h"
#import "GYQBaseBarItem.h"
@implementation HWNavigationController
    
    

#pragma mark - 设置导航栏主题


+ (void) setttingAppearance{
    //设置全局导航条外观
    [self settingUINavigationBarAppearance];
    if (IOS7) {
        return;//不需要设置全局导航条按钮主题
    }
    //设置全局导航条按钮主题
    [self settingbarButtonItenAppearance];
}


settingUINavigationBarAppearance

+ (void) settingUINavigationBarAppearance{
    /*
     @protocol UIAppearance <NSObject>  协议的代理方法+ (instancetype)appearance;
     
     @interface UIView : UIResponder < UIAppearance>
     */
    //方式一:获取全局外观
    //    UINavigationBar *navigationBar =[UINavigationBar appearance];//获取所有导航条外观
    //方式二:获取我们自己导航控制器的导航条-- 确保系统的其它功能(短信)的导航条与自己的冲突,尤其在短信分享这方面要注意
    UINavigationBar *navigationBar;
    if (IOS9) {
        //9.0的API
        navigationBar = [UINavigationBar appearanceWhenContainedInInstancesOfClasses:@[[HWNavigationController class]]];
    }else{
        navigationBar = [UINavigationBar appearanceWhenContainedIn:[HWNavigationController class],nil];
    }
    
    /**
     导航栏背景的出图规格
     iOS6导航栏背景的出图规格
     非retina:320x44 px
     retina:640x88 px
     iOS7导航栏背景的出图规格
     retina:640x128 px
     */
    
    
    
    [self setupUINavigationBarsetBackgroundImage:navigationBar];
    /*2.
     *标题:@property(nonatomic,copy) NSDictionary *titleTextAttributes;// 字典中能用到的key在UIStringDrawing.h中// 最新版本的key在UIKit框架的NSAttributedString.h中
     
     */
    //    NSDictionary *dict = @{UITextAttributeTextColor:[UIColor whiteColor]};
    NSDictionary *dict = @{NSForegroundColorAttributeName:[UIColor whiteColor],NSFontAttributeName:kNavListNSFontAttributeName};
    [navigationBar setTitleTextAttributes:dict];
    //2、The tint color to apply to the navigation items and bar button items. 导航条的主题颜色
    [navigationBar setTintColor:[UIColor whiteColor]];
    
    
}

1.3 设置导航条渐变颜色

setupUINavigationBarsetBackgroundImage

+ (void)setupUINavigationBarsetBackgroundImage:(UINavigationBar*)navigationBar{
    
    UIImage *bgImg = [UIImage getMaingradientColorImage];
    [navigationBar setBackgroundImage:bgImg forBarMetrics:UIBarMetricsDefault];

    
}



1.4 拦截push


#pragma mark - 拦截push;--//90%的拦截,都是通过自定义类,重写自带的方法实现
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated{
    if (self.viewControllers.count>0) {
        
        [self setNavigationBarHidden:NO animated:NO];
        viewController.hidesBottomBarWhenPushed =YES;
        

        
        if ([viewController respondsToSelector:@selector(KNbackAction)]) {
            
            UIBarButtonItem *tmp =[[UIBarButtonItem alloc]initWithImage:[UIImage imageNamed:QCTNAVicon_left] style:0 target:viewController action:@selector(KNbackAction)];

            viewController.navigationItem.leftBarButtonItem = tmp;

        }else{
            
            UIBarButtonItem *tmp =[[UIBarButtonItem alloc]initWithImage:[UIImage imageNamed:QCTNAVicon_left] style:0 target:self action:@selector(backAction)];
            viewController.navigationItem.leftBarButtonItem = tmp;

        }

        
        
        
        
        
    }
    [super pushViewController:viewController animated:animated];

}
#pragma mark - 重写: animated:
/**
 1)自定义导航控制器的价值
 重写push方法就可以拦截所有压入栈中的子控制器,统一做一些处理
 */
    
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion{
    
    
    
//    if ([[viewControllerToPresent topViewController] respondsToSelector:@selector(KNprebackAction)]) {

        
        if ( [viewControllerToPresent  isKindOfClass:[UINavigationController class]]) {
            
            
            
            
            

            
            
            UINavigationController  *viewControllerToPresenttmp = (UINavigationController*)viewControllerToPresent;
            
            weakSelf(weakSelf);

            if ([[viewControllerToPresenttmp topViewController] respondsToSelector:@selector(KNprebackAction)]) {
                
                GYQBaseBarItem *tmp =[[GYQBaseBarItem alloc]initWithImage:[UIImage imageNamed:QCTNAVicon_left] style:0 target:[viewControllerToPresenttmp topViewController] action:@selector(KNprebackAction)];
                tmp.baseVC = viewControllerToPresent;
                viewControllerToPresenttmp.topViewController.navigationItem.leftBarButtonItem = tmp;

                
                
            }else{
                
                GYQBaseBarItem *tmp =[[GYQBaseBarItem alloc]initWithImage:[UIImage imageNamed:QCTNAVicon_left] style:0 target:weakSelf action:@selector(presenbackAction:)];
                tmp.baseVC = viewControllerToPresent;
                viewControllerToPresenttmp.topViewController.navigationItem.leftBarButtonItem = tmp;

            }

            
        }

        
        
    
    [super presentViewController:viewControllerToPresent animated:flag completion:completion];
}
    
-(void)presenbackAction:(GYQBaseBarItem *)bar{
    
    //一旦点击返回,就要打断首次流程
    [bar.baseVC dismissViewControllerAnimated:YES completion:nil];
}
    
- (void)backAction{
    
    [self popViewControllerAnimated:YES];

    
    
    
}

1.5 去掉透明后导航栏下边的黑边

iOS15之前 [self.navigationBar setShadowImage:[[UIImage alloc] init]];

iOS15之后


    if(@available(iOS 15.0, *)) {
        UINavigationBarAppearance *appearance = [[UINavigationBarAppearance alloc] init];
        
        //去掉透明后导航栏下边的黑边
        appearance.shadowImage =[[UIImage alloc] init];
        
        appearance.shadowColor= UIColor.clearColor;


        
        navigationBar.standardAppearance = appearance;
        
        navigationBar.scrollEdgeAppearance = appearance;
        
    }



II、相关代码

#define kAdjustRatio(num) (ceil((SCREENW/375.0)*(num)))

#define kPingFangFont(fontSize) [UIFont fontWithName:@"PingFang-SC-Medium" size:(kAdjustRatio(fontSize))]

#define kTextFont(size) [UIFont systemFontOfSize:(kAdjustRatio(size))]


#define kPingFangHeavyFont(fontSize) [UIFont fontWithName:@"PingFang-SC-Heavy" size:(kAdjustRatio(fontSize))]

#define kPingFangNOkAdjustRatioFont(fontSize) [UIFont fontWithName:@"PingFang-SC-Medium" size:((fontSize))]



#define kBoldFont(fontSize) [UIFont fontWithName:@"Helvetica-Bold" size:(kAdjustRatio(fontSize))]


  • searchBar 的searchField 的获取

 UITextField *searchField = [searchBar valueForKey:@"searchField"];
    
    [searchField setBackgroundColor:HWColor(245, 245, 245)];

获取 navigationBar

if (IOS9) {
        //9.0的API
        navigationBar = [UINavigationBar appearanceWhenContainedInInstancesOfClasses:@[[GYQNavigationControllerViewController class]]];
        
        
        [[UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setTintColor:[UIColor blackColor]];

        
        
    }else{
        navigationBar = [UINavigationBar appearanceWhenContainedIn:[GYQNavigationControllerViewController class],nil];
        
        [[UIBarButtonItem appearanceWhenContainedIn: [UISearchBar class], nil] setTintColor:[UIColor blackColor]];

    }
    [navigationBar setShadowImage:[ImageTools createImageWithColor: QBW221Color]];


see also

更多内容请关注#小程序:iOS逆向,只为你呈现有价值的信息,专注于移动端技术研究领域。