iOS小技能:自定义导航栏,设置全局导航条外观。(iOS15适配)

1,077 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第30天,点击查看活动详情

前言

需求:同一个模块的主题要求是一致的 实现:通过自定义导航条来进行统一控制样式

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

I 自定义导航栏

1.1 自定义导航条

#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适配)

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

        [vc.navigationController.navigationBar setBackgroundImage:[ImageTools createImageWithColor: [UIColor whiteColor]] forBarMetrics:UIBarMetricsDefault];

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;
        
    }



1.6 设置导航栏下边的黑边(iOS13适配)



// 设置导航栏下边的黑边
+ (void)setupnavigationBar:(UIViewController*)vc{
    
    
    
    if (@available(iOS 13.0, *)) {
        
        UINavigationBar *navigationBar = vc.navigationController.navigationBar;

        UINavigationBarAppearance *appearance =navigationBar.standardAppearance;
        
    
        appearance.shadowImage =[UIImage createImageWithColor:k_tableView_Line];

        appearance.shadowColor=k_tableView_Line;
        

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

    } else {
        // Fallback on earlier versions
        
        UINavigationBar *navigationBar = vc.navigationController.navigationBar;
        [navigationBar setBackgroundImage:[[UIImage alloc] init] forBarPosition:UIBarPositionAny barMetrics:UIBarMetricsDefault]; //此处使底部线条颜色为红色
//        [navigationBar setShadowImage:[UIImage createImageWithColor:[UIColor redColor]]];
        
        [navigationBar setShadowImage:[UIImage createImageWithColor:k_tableView_Line]];
        
    }


    
}



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逆向,只为你呈现有价值的信息,专注于移动端技术研究领域。

自定义时间格式(适配iOS15.4之后12/24小时制的问题):blog.csdn.net/z929118967/…