🔥 NXNavigationExtension is a lightweight navigation bar handling framework for iOS apps that supports both SwiftUI and UIKit. The framework has very little intrusion into existing code and requires only a few simple method calls to satisfy most application scenarios. Probably one of the most effortless iOS navigation frameworks out there. The NXNavigationExtension framework itself and the sample code have been adapted to dark mode for your reference. Address: github.com/l1Dan/NXNav… , welcome to Star 🌟 and PR.

Also attached is a UIKit tutorial

🎉 preview

SwiftUI routing Fully custom navigation bar Return event interception Modify the appearance of the navigation bar

🌟 Start using

Download the NXNavigationExtension sample code.

Integrate using CocoaPods

To integrate the NXNavigationExtension into your Xcode project using CocoaPods, specify in your Podfile:

## For SwiftUI
pod 'NXNavigationExtension/SwiftUI'

## For UIKit
pod 'NXNavigationExtension'
Copy the code

Use Carthage for management

Use Carthage to manage the NXNavigationExtension Framework, please add the following to your Cartfile:

# For SwiftUI
github "l1Dan/NXNavigationExtension" # Requires
github "l1Dan/NXNavigationExtensionSwiftUI"

# For UIKit
github "l1Dan/NXNavigationExtension"

Copy the code

Integrate using Swift Package Manager

To integrate with the NXNavigationExtension using Swift Package Manager, add the following to the dependencies of your package.swift file:

dependencies: [
    .package(url: "https://github.com/l1Dan/NXNavigationExtension.git", .upToNextMajor(from: "4.0.2.")))Copy the code

🌈 requirements

The latest version supports iOS 9.0 at least

NXNavigationExtension Version Minimum iOS Target Minimum macOS Target Frameworks Note
4.x IOS 9.0 MacOS 10.15 SwiftUI, UIKit, macCatalyst Xcode13, SwiftUI 2.0
3.x IOS 9.0 MacOS 10.15 UIKit, macCatalyst /
2.x IOS 11.0 MacOS 10.15 UIKit, macCatalyst /

advantages

  • API design is easy to understand, easy to use.
  • No inheritance relationship, all operations based on classification implementation, low coupling.
  • In whitelist mode, the navigation controllers used are registered on demand so that all navigation controller appearances are not affected.
  • There are no changes to the native navigation bar view hierarchy, so there is no need to worry about compatibility with system upgrades.
  • IOS, iPadOS, macOS, vertical and horizontal switching, dark mode.
  • SwiftUI, UIKit, macCatalyst framework support.
  • Supports integration through CocoaPods, Carthage, Project, and Swift Package Manager.

👏 function

Some of these extra useful features will fit your project

The basic function

  • Make the navigation bar transparent
  • Realize the fuzzy effect of the system navigation bar
  • Custom return button image
  • Custom return button
  • Custom navigation bar blur background
  • Change the color of the back button arrow
  • Modify the text of the system return button
  • Modify the navigation bar title color
  • Modify the background color of the navigation bar
  • Modify the background image of navigation bar
  • Change the color of the bottom line of the navigation bar
  • Modify the bottom line image of the navigation bar

Advanced features

  • Disable the swipe back gesture
  • Enable the full screen swipe back gesture
  • Navigation bar returns to event interception
  • Redirects to any controller
  • SwiftUI routing
  • Navigation bar click event to penetrate to the bottom
  • Dynamically modify navigation bar styles
  • Update navigation bar styles
  • Gradient navigation style
  • Long press back button to display menu function
  • See sample code for more…

🍽 use

NXNavigationExtensionSwiftUI by NXNavigationExtension framework to provide strong support, the function of their basic consistent. NavigationViewStyle (.stack) : navigationViewStyle(.stack) : navigationViewStyle(.stack) : navigationViewStyle(.stack) : navigationViewStyle(.stack) : navigationViewStyle(.stack) Other systems and NavigationViewStyle will be improved over time.

StackNavigationViewStyle and iOS versions are supported by the framework below:

NavigationViewStyle / iOS version iOS 13 iOS 14 iOS 15
.automatic
.stack
.columns
  1. 💉 Import the module.

    • useCocoaPodsIntegration:import NXNavigationExtension
    • useCarthageManagement:import NXNavigationExtensionSwiftUI
  2. 💉 You need to register the navigation controller to be modified in the AppDelegate before using it.

✅ recommended

Really only need NXNavigationConfiguration in UIKit version () registerNavigationControllerClasses ([YourNavigationController. Self]) This line of code completes the registration of the navigation controller. But in SwiftUI version also need an extra step: specify NXNavigationVirtualWrapperView lookup rules, he is a bridge between SwiftUI with UIKit. Lookup rules developers can customize or use the default lookup rules provided by the framework.

// AppDelegate.swift
var classes: [AnyClass] = []
    if #available(iOS 15.0.*) {
        classes = [
            NSClassFromString("SwiftUI.SplitViewNavigationController"),
            NSClassFromString("SwiftUI.UIKitNavigationController"),
        ].compactMap { $0}}else {
        classes = [
            NSClassFromString("SwiftUI.SplitViewNavigationController"), // iOS14
        ].compactMap { $0}}let defaultConfiguration = NXNavigationConfiguration.default
    defaultConfiguration.registerNavigationControllerClasses(classes) { navigationController, configuration in
        // Configure
        navigationController.nx_applyFilterNavigationVirtualWrapperViewRuleCallback(NXNavigationVirtualView.configureWithDefaultRule(for:))
        return configuration
}
Copy the code
// Example: ContentView.swift
import SwiftUI
import NXNavigationExtension

struct DestinationView: View {
    @State private var context: NXNavigationRouter.Context = NXNavigationRouter.Context(routeName: "/destinationView")

    var body: some View {
        Button {
            // NXNavigationRouter.of(context).pop()
            NXNavigationRouter.of(context /* /destinationView */).popUntil("/contentView")
        } label: {
            Text("Pop")
                .padding()
        }
        .useNXNavigationView(context: $context, onPrepareConfiguration: { configuration in
            // `DestinationView` NavigationView backgroundColor
            configuration.navigationBarAppearance.backgroundColor = .red
        })
    }

}

struct ContentView: View {
    @State private var context: NXNavigationRouter.Context = NXNavigationRouter.Context(routeName: "/contentView")

    var body: some View {
        NavigationView {
            NavigationLink { // 1. Use NavigationView wrapper
                DestinationView()
            } label: {
                Text("Push")
                    .padding()
                    .useNXNavigationView(context: $context /* /contentView */, onPrepareConfiguration: { configuration in
                        // 3. Change the background color of navigation bar... `Text` NavigationView backgroundColor
                        configuration.navigationBarAppearance.backgroundColor = .brown
                    })
            }
        }
        .navigationViewStyle(.stack) // 2. Use StackNavigationViewStyle}}Copy the code

🍻 Basic Functions

Change the color of the back button arrow

📝 Sample code

Text("Destination")
    .useNXNavigationView(onPrepareConfiguration: { configuration in
        configuration.navigationBarAppearance.tintColor = .red
    })
Copy the code

Modify the text of the system return button

📝 Sample code

Text("Destination")
    .useNXNavigationView(onPrepareConfiguration: { configuration in
        configuration.navigationBarAppearance.useSystemBackButton = true
        configuration.navigationBarAppearance.systemBackButtonTitle = title
    })
Copy the code

Modify the navigation bar title color

📝 Sample code

Text("Destination")
    .useNXNavigationView(onPrepareConfiguration: { configuration in
        configuration.navigationBarAppearance.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.black]
    })
Copy the code

Modify the background color of the navigation bar

The default background color of the navigation bar is system blueUIColor.systemBlue, which can quickly tell if the framework is working or not. You can also rewrite it in the following ways:

📝 Sample code

// Global unified change
let configuration = NXNavigationConfiguration.default
configuration.navigationBarAppearance.backgroundColor = .red

// Modify based on view controller
Text("Destination")
    .useNXNavigationView(onPrepareConfiguration: { configuration in
        configuration.navigationBarAppearance.backgroundColor = .red
    })
Copy the code

Modify the background image of navigation bar

📝 Sample code

Text("Destination")
    .useNXNavigationView(onPrepareConfiguration: { configuration in
        configuration.navigationBarAppearance.backgroundImage = UIImage(named: "NavigationBarBackground88")})Copy the code

Make the navigation bar transparent

📝 Sample code

Text("Destination")
    .useNXNavigationView(onPrepareConfiguration: { configuration in
        configuration.navigationBarAppearance.backgroundColor = .clear
        configuration.navigationBarAppearance.shadowColor = .clear
    })
Copy the code

Realize the fuzzy effect of the system navigation bar

📝 Sample code

Text("Destination")
    .useNXNavigationView(onPrepareConfiguration: { configuration in
        configuration.navigationBarAppearance.backgroundColor = .clear
        configuration.viewControllerPreferences.useBlurNavigationBar = true
    })
Copy the code

Change the color of the bottom line of the navigation bar

📝 Sample code

Text("Destination")
    .useNXNavigationView(onPrepareConfiguration: { configuration in
        configuration.navigationBarAppearance.backgroundColor = .systemBackground
        configuration.navigationBarAppearance.shadowColor = .systemRed
    })
Copy the code

Modify the bottom line image of the navigation bar

📝 Sample code

Text("Destination")
    .useNXNavigationView(onPrepareConfiguration: { configuration in
        configuration.navigationBarAppearance.backgroundColor = .systemBackground
        configuration.navigationBarAppearance.shadowImage = UIImage(named: "NavigationBarShadowImage")})Copy the code

Custom return button image

📝 Sample code

Text("Destination")
    .useNXNavigationView(onPrepareConfiguration: { configuration in
        configuration.navigationBarAppearance.backImage = UIImage(systemName: "arrow.left")})Copy the code

Custom return button

📝 Sample code

Text("Destination")
    .useNXNavigationView(onPrepareConfiguration: { configuration in
        configuration.navigationBarAppearance.backButtonCustomView = backButton
    })
Copy the code

🍺 Advanced Functions

Disable the swipe back gesture

📝 Sample code

Text("Destination")
    .useNXNavigationView(onPrepareConfiguration: { configuration in
        configuration.viewControllerPreferences.disableInteractivePopGesture = true
    })
Copy the code

Enable the full screen swipe back gesture

📝 Sample code

  • Effective global
let configuration = NXNavigationConfiguration.default
configuration.viewControllerPreferences.enableFullScreenInteractivePopGesture = true
Copy the code
  • Locally valid (set on page)
Text("Destination")
    .useNXNavigationView(onPrepareConfiguration: { configuration in
        configuration.viewControllerPreferences.enableFullScreenInteractivePopGesture = true
    })
Copy the code

Navigation bar returns to event interception

📝 Sample code

  1. .callNXPopMethod: callnx_popA series of methods return event interception.
  2. .backButtonAction: Click the back button to return to event interception.
  3. .backButtonMenuAction: Long press the back button to select the menu to return to event interception.
  4. .popGestureRecognizer: Returns event interception using gesture interaction.
Text("Destination")
    .useNXNavigationView(onWillPopViewController: { interactiveType in
        if selectedItemType = = .backButtonAction && interactiveType = = .backButtonAction ||
            selectedItemType = = .backButtonMenuAction && interactiveType = = .backButtonMenuAction ||
            selectedItemType = = .popGestureRecognizer && interactiveType = = .popGestureRecognizer ||
            selectedItemType = = .callNXPopMethod && interactiveType = = .callNXPopMethod ||
            selectedItemType = = .all {
            isPresented = true
            return false
        }
        return true
    })
Copy the code

SwiftUI routing

📝 Sample code

struct DestinationView: View {
    @State private var context: NXNavigationRouter.Context

    init(a) {
        context = NXNavigationRouter.Context(routeName: "/currentRouteName")}var body: some View {
        VStack {
            Button {
                NXNavigationRouter.of(context).pop()
            } label: {
                Text("Pop")
            }
            .useNXNavigationView(context: $context)}}}Copy the code
  1. One thing to noteNXNavigationRouter.of(context)NXNavigationRouter.of(context).nxUsed to call the systempopAnd frameworknx_popSeries method
  2. useNXNavigationRouter.of(context).nxMethod is triggered when a page pops uponWillPopViewControllerThe callback.

Navigation bar click event to penetrate to the bottom

📝 Sample code

Text("Destination")
    .useNXNavigationView(onPrepareConfiguration: { configuration in
        configuration.viewControllerPreferences.translucentNavigationBar = true
    })
Copy the code

Update navigation bar styles

📝 Sample code

Button {
    NXNavigationRouter.of(context).setNeedsNavigationBarAppearanceUpdate()
} label: {
    Text("Update")}Copy the code

Long press back button to display menu function

📝 Sample code

Text("Destination")
    .useNXNavigationView(onPrepareConfiguration: { configuration in
        configuration.navigationBarAppearance.useSystemBackButton = true
    })
Copy the code

FAQ Frequently Asked Questions

Q: why can’t iOS14 and later change the appearance of the navigation bar even after registering UIImagePickerController and PHPickerViewController classes?

A: Because UINavigationBar in UIImagePickerController and PHPickerViewController is hidden, NXNavigationBar will follow the system navigation bar to hide and show, So you can’t change it (you can change UIImagePickerController before iOS14). And PHPickerViewController is actually a subclass of UIViewController, so you can display your controller as push or present, and they all have one thing in common: they all use a fake navigation bar.


Q: why iOS13 before using the self. The navigationItem. SearchController set UISearchBar unable to follow the change of the navigation bar, after iOS13 can?

A: because UISearchBar was not included in the navigation bar before iOS13, UISearchBar was included in the navigation bar after iOS13. See the sample code for details.


Q: How to resolve the conflict between UIScrollView and UIPageViewController full screen gestures?

A: Use UIScrollView and UIPageViewController full screen gesture conflict solution.


Q: Why does the NXNavigationExtension framework not include transition animation for controllers?

A: The principle is to keep the framework as simple and light as possible, spend more energy on the stability of the framework itself, and use the original functions of the system as much as possible. Transitions are not suitable for all business scenarios and are not a feature of the framework. If you have a transition animation requirement that needs to be implemented by the developer, you can also refer to the VCTransitionsLibrary or sample code.


Q: Why is the position of the system return button arrow in the navigation bar inconsistent with that of the custom return button arrow?

A: because the navigation system back button is with the self. The navigationItem. BackBarButtonItem attribute to set. And custom back button is with the self. The navigationItem. LeftBarButtonItem attribute to set, their position would not have been the same. Of course you can use the system back button, set whether to use the system back button with the (nx_)useSystemBackButton property, and set the title of the system back button with the (nx_)systemBackButtonTitle property. The offset of the custom return button image is also controlled by the (nx_)backImageInsets or (nx_)landscapeBackImageInsets property.

  • The back button arrow should be left rather than center in the cutout, and the transparent background should be left on the right.
  • usenx_backButtonCustomViewProperty to customize the return button requires the developer to correct the offset of the arrow.

📄 agreement

The NXNavigationExtension framework is distributed under license from MIT. For details, see LICENSE.