iOS 导航栏方案框架 NXNavigationExtensio

2021-10-09  本文已影响0人  l1Dan

🔥 NXNavigationExtension 是为 iOS 应用设计的一个轻量级的导航栏处理框架。框架对现有代码入侵非常小,只需要简单的几个方法调用就可以满足大部分的应用场景。NXNavigationExtension 和 示例程序代码 都已经适配暗黑模式(Dark Mode)。

🎉 预览

Preview

🌟 开始使用

下载 NXNavigationExtension 示例代码。

使用 CocoaPods 安装

使用 CocoaPods 将 NXNavigationExtension 集成到 Xcode 项目中,需要在 Podfile 中指定:

pod 'NXNavigationExtension'

使用 Carthage 安装

Carthage 是一个去中心化的包管理器,它构建依赖项并为您提供二进制框架。 要集成 NXNavigationExtension,请将以下内容添加到您的 Cartfile 文件中:

github "l1Dan/NXNavigationExtension"

🌈 要求

最新版本最低支持 iOS 9.0

NXNavigationExtension Version Minimum iOS Target Minimum macOS Target Notes
3.x iOS 9.0 macOS 10.15 macOS: macCatalyst
2.x iOS 11 macOS 10.15 macOS: macCatalyst

优点

👏 功能

特别实用的功能,总有一款适合你的项目

基本功能

高级功能

🍽 使用

所有对导航栏外观的修改都是基于视图控制器 UIViewController 修改的,而不是基于导航控制器 UINavigationController 修改,这种设计逻辑更加符合实际应用场景。也就是说视图控制器管理自己的导航栏,而不是使用导航控制器来全局管理。

  1. 💉 导入头文件 #import <NXNavigationExtension/NXNavigationExtension.h>
  2. 💉 使用之前需要先注册需要修改的导航控制器。

✅ 推荐

NXNavigationConfiguration *configuration = [NXNavigationConfiguration defaultConfiguration];
configuration.navigationBarAppearance.tintColor = [UIColor customTitleColor];
[configuration registerNavigationControllerClasses:@[[FeatureNavigationController class]] prepareConfigureViewControllerCallback:^NXNavigationConfiguration * _Nullable(__kindof UIViewController * _Nonnull viewController, NXNavigationConfiguration * _Nonnull configuration) {
    configuration.navigationBarAppearance.backgroundColor = [UIColor brownColor];
    return configuration;
}];

// OR
NXNavigationConfiguration *otherConfiguration = [[NXNavigationConfiguration alloc] init];
otherConfiguration.navigationBarAppearance.tintColor = [UIColor customTitleColor];
[otherConfiguration registerNavigationControllerClasses:@[[OtherNavigationController class]]];

❌ 不推荐

NXNavigationConfiguration *configuration = [[NXNavigationConfiguration alloc] init];
configuration.navigationBarAppearance.tintColor = [UIColor customTitleColor];
// UINavigationController 会影响所有的导航控制器,所以不推荐使用这种方式注册
[configuration registerNavigationControllerClasses:@[[UINavigationController class]]];

注意

建议:除非你非常明白修改全局性东西的后果,否则不要修改,这么做的原因就是为了减少走一些弯路!

🍻 基本功能

修改返回按钮箭头颜色

📝 示例代码

导航栏返回按钮颜色默认使用系统蓝色 [UIColor systemBlueColor],要改变返回按钮颜色可以使用以下方式配合:

// 全局统一修改,不会覆盖基于视图控制器修改
NXNavigationConfiguration *configuration = [[NXNavigationConfiguration alloc] init];
configuration.navigationBarAppearance.tintColor = [UIColor redColor];

// 基于视图控制器修改
- (UIColor *)nx_barTintColor {
    return self.isDarkMode ? [UIColor whiteColor] : [UIColor blackColor];
}

修改系统返回按钮文字

📝 示例代码

// 需要设置使用系统返回按钮,这样才会有效果
- (BOOL)nx_useSystemBackButton {
    return YES;
}

- (NSString *)nx_systemBackButtonTitle {
    return self.backButtonTitle;
}

修改导航栏标题颜色

📝 示例代码

- (NSDictionary<NSAttributedStringKey,id> *)nx_titleTextAttributes {
    return @{NSForegroundColorAttributeName: [self nx_barTintColor]};
}

修改导航栏背景颜色

📝 示例代码

- (UIColor *)nx_navigationBarBackgroundColor {
    return [UIColor customDarkGrayColor];
}

修改导航栏背景图片

📝 示例代码

- (UIImage *)nx_navigationBarBackgroundImage {
    return UIImage.navigationBarbackgroundImage;
}

设置导航栏透明

📝 示例代码

- (UIColor *)nx_navigationBarBackgroundColor {
    return [UIColor clearColor];
}

实现系统导航栏模糊效果

📝 示例代码

- (UIColor *)nx_navigationBarBackgroundColor {
    return [UIColor clearColor];
}

- (BOOL)nx_useBlurNavigationBar {
    return YES;
}

修改导航栏底部线条颜色

📝 示例代码

- (UIColor *)nx_shadowImageTintColor {
    return [UIColor redColor];
}

修改导航栏底部线条颜色图片

📝 示例代码

- (UIColor *)nx_shadowImageTintColor {
    return [UIColor redColor];
}

修改导航栏底部线条颜色图片

📝 示例代码

- (UIImage *)nx_shadowImage {
    return [UIImage imageNamed:@"NavigationBarShadowImage"];
}

自定义返回按钮图片

📝 示例代码

- (UIImage *)nx_backImage {
    return [UIImage imageNamed:@"NavigationBarBack"];
}

自定义返回按钮

📝 示例代码

- (UIView *)nx_backButtonCustomView {
    UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
    [backButton setTitle:@"😋" forState:UIControlStateNormal];
    [backButton setImage:[UIImage imageNamed:@"NavigationBarBack"] forState:UIControlStateNormal];
    [backButton setTitleColor:UIColor.customDarkGrayColor forState:UIControlStateNormal];
    return backButton;
}

🍺 高级功能

禁用滑动返回手势

📝 示例代码

- (BOOL)nx_disableInteractivePopGesture {
    return YES;
}

启用全屏滑动返回手势

📝 示例代码

- (BOOL)nx_enableFullscreenInteractivePopGesture {
    return YES;
}
NXNavigationConfiguration *configuration = [[NXNavigationConfiguration alloc] init];
configuration.navigationControllerPreferences.fullscreenInteractivePopGestureEnabled = YES;

导航栏返回事件拦截

📝 示例代码

需要遵守协议 <NXNavigationInteractable>,实现代理方法:

- (BOOL)nx_navigationController:(__kindof UINavigationController *)navigationController willPopViewController:(__kindof UIViewController *)viewController interactiveType:(NXNavigationInteractiveType)interactiveType {
    // TODO...
    return YES;
}
  1. NXNavigationInteractiveTypeCallNXPopMethod: 调用 nx_pop 系列方法返回事件拦截。
  2. NXNavigationInteractiveTypeBackButtonAction: 点击返回按钮返回事件拦截。
  3. NXNavigationInteractiveTypeBackButtonMenuAction: 长按返回按钮选择菜单返回事件拦截。
  4. NXNavigationInteractiveTypePopGestureRecognizer: 使用手势交互返回事件拦截。
- (BOOL)nx_navigationController:(__kindof UINavigationController *)navigationController willPopViewController:(__kindof UIViewController *)viewController interactiveType:(NXNavigationInteractiveType)interactiveType {
    NSLog(@"interactiveType: %zd %@", interactiveType, viewController);

    if (self.currentItemType == EventInterceptItemTypeBackButtonAction && interactiveType == NXNavigationInteractiveTypeBackButtonAction) {
        [self showAlertControllerWithViewController:viewController];
        return NO;
    }

    if (self.currentItemType == EventInterceptItemTypeBackButtonMenuAction && interactiveType == NXNavigationInteractiveTypeBackButtonMenuAction) {
        [self showAlertControllerWithViewController:viewController];
        return NO;
    }

    if (self.currentItemType == EventInterceptItemTypePopGestureRecognizer && interactiveType == NXNavigationInteractiveTypePopGestureRecognizer) {
        [self showAlertControllerWithViewController:viewController];
        return NO;
    }

    if (self.currentItemType == EventInterceptItemTypeCallNXPopMethod && interactiveType == NXNavigationInteractiveTypeCallNXPopMethod) {
        [self showAlertControllerWithViewController:viewController];
        return NO;
    }

    if (self.currentItemType == EventInterceptItemTypeAll) {
        [self showAlertControllerWithViewController:viewController];
        return NO;
    }

    return YES;
}

自定义返回按钮事件需要拦截可以调用 nx_popViewControllerAnimated:nx_popToViewController:animated:nx_popToRootViewControllerAnimated: 等方法来触发上面的代理回调。

重定向任一控制器跳转

📝 示例代码

[self.navigationController nx_redirectViewControllerClass:[RandomColorViewController class] initializeStandbyViewControllerUsingBlock:^__kindof UIViewController * _Nonnull {
    return [[RandomColorViewController alloc] init];
}];

注意
执行上面代码之后并不会立即跳转,下面代码可以实现立即跳转:

[self.navigationController nx_redirectViewControllerClass:[RandomColorViewController class] initializeStandbyViewControllerUsingBlock:^__kindof UIViewController * _Nonnull {
    return [[RandomColorViewController alloc] init];
}];
[self.navigationController popViewControllerAnimated:YES];

意思是:首先查找 self.navigationController.ViewConrollers 是否存在一个类型为 [RandomColorViewController class] 的实例对象,如果存在则重定向到此视图控制器,没有则使用 [[RandomColorViewController alloc] init] 来创建一个新的 [RandomColorViewController class] 的实例对象。

导航栏点击事件穿透到底部

📝 示例代码

- (BOOL)nx_translucentNavigationBar {
    return YES;
}

动态修改导航栏样式

📝 示例代码

- (BOOL)nx_contentViewWithoutNavigtionBar {
    return YES;
}

可以动态调整 contentView 透明度实现:self.nx_navigationBar.contentView.alpha = value

更新导航栏样式

📝 示例代码

[self nx_setNeedsNavigationBarAppearanceUpdate];

如果状态栏样式没有发生变化,请检查是否需要调用方法 [self setNeedsStatusBarAppearanceUpdate],或者在 UINavigationController 的子类中设置如下代码:

- (UIViewController *)childViewControllerForStatusBarStyle {
    return self.topViewController;
}

- (UIViewController *)childViewControllerForStatusBarHidden {
    return self.topViewController;
}

长按返回按钮显示菜单功能

📝 示例代码

- (BOOL)nx_useSystemBackButton {
    return YES;
}
BackButtonMenu

FAQ 常见问题

Q:iOS14 及之后的版本为什么注册了 UIImagePickerControllerPHPickerViewController 类之后还是无法修改导航栏的外观?

A:因为 UIImagePickerControllerPHPickerViewController 里面的 UINavigationBar 是隐藏的,NXNavigationBar 会跟随系统导航栏隐藏与显示,所以无法修改(iOS14 之前系统的 UIImagePickerController 是可以修改的)。另外 PHPickerViewController 其实是一个 UIViewController 的子类,你既可以用 push 的方式显示控制器也可以用 present 的方式显示控制器,他们有个共同特点:使用的都是一个 “假” 的导航栏。


Q:为什么 iOS13 之前使用 self.navigationItem.searchController 设置的 UISearchBar 无法跟随导航栏的变化而变化,iOS13 之后的却可以呢?

A:因为在 iOS13 之前导航栏中不包含 UISearchBar,iOS13 之后导航栏才包含 UISearchBar 的。具体使用请参考示例代码


Q:如何解决 UIScrollViewUIPageViewController 手势冲突?

A:使用 UIScrollViewUIPageViewController 手势冲突解决方案。


Q:为什么 NXNavigationExtension 框架不包含控制器的转场动画功能?

A:原则就是尽可能的保持框架的简单轻量,将更多的精力花在框架本身的稳定性上,尽可能地使用系统原有功能。转场动画功能并不适用于所有业务场景,另外也不属于这个框架的功能。如果有转场动画的需求需要开发者自己实现,也可以参考VCTransitionsLibrary,或者参考示例代码


Q:为什么导航栏的系统返回按钮箭头和自定义返回按钮箭头的位置不一致?

A:因为导航栏的系统返回按钮是用 self.navigationItem.backBarButtonItem 属性来设置的。而自定义返回按钮是用 self.navigationItem.leftBarButtonItem 属性来设置的,他们的位置本来就不一样。当然你可以使用系统返回按钮,通过 (nx_)useSystemBackButton 属性设置是否使用系统返回按钮,再配合 (nx_)systemBackButtonTitle 属性设置系统返回按钮的标题。还可以通过 (nx_)backImageInsets 或者 (nx)landscapeBackImageInsets 属性来控制自定义返回按钮图片的偏移量。


📄 协议

NXNavigationExtension 框架是在 MIT 许可下发布的。详情请参见 LICENSE

地址: https://github.com/l1Dan/NXNavigationExtension

上一篇 下一篇

猜你喜欢

热点阅读