Router is a library that assists with SwiftUI view transitions.

Overview

SwiftUI Router

Router

Router is a library that assists with SwiftUI view transitions.

Installation

.package(name: "Router", url: "[email protected]:1amageek/Router.git", .upToNextMajor(from: "0.2.0")),

Usage

Router

The Router specifies the View to be navigated. The argument of Router is the Path of the first View to be displayed. By default, / is specified.

Route

Route will show the View of the Path specified in the argument. Path has placeholders and the parameters can be accessed from context.

import SwiftUI
import Router

struct ContentView: View {

    @State var isShow: Bool = false

    var body: some View {
        Router("/weather") {
            Route("/weather") { 
                ListView()
            }
            Route("/weather/{weatherLabel}") { context in
                DetailView(label: context.paramaters["weatherLabel"]!)
            }
        }
        .environmentObject(DataStore())
    }
}

Navigator

It transitions between screens by giving Navigator a path. You can specify the transition animation. In the example below, we call the push animation.

struct ListView: View {

    @Environment(\.navigator) private var navigator: Binding<Navigator>

    @EnvironmentObject var dataStore: DataStore

    var body: some View {

        List {
            Section(header:
                        Text("Weather")
                        .font(.system(size: 24, weight: .black, design: .rounded))
                        .padding()
            ) {
                ForEach(dataStore.data, id: \.label) { data in
                    Button(action: {
                        navigator.push {
                            navigator.wrappedValue.path = "/weather/\(data.label)"
                        }
                    }) {
                        Label(data.title, systemImage: data.systemImage)
                            .font(.system(size: 20, weight: .bold, design: .rounded))
                        Spacer()
                    }
                    .buttonStyle(PlainButtonStyle())
                }
            }
        }
        .listStyle(InsetGroupedListStyle())
    }
}

Navigator is defined as an environment, so it can be called from anywhere.

struct DetailView: View {

    @Environment(\.navigator) private var navigator: Binding<Navigator>

    @EnvironmentObject var dataStore: DataStore

    var label: String

    var weather: Weather? {
        return self.dataStore.data.filter({$0.label == self.label}).first
    }

    var body: some View {
        ZStack {
            VStack(spacing: 10) {
                Image(systemName: self.weather!.systemImage)
                    .font(.system(size: 120, weight: .bold, design: .rounded))
                Text(label)
                    .font(.system(size: 30, weight: .bold, design: .rounded))
            }
            VStack(alignment: .leading) {
                HStack {
                    Button(action: {
                        navigator.pop {
                            navigator.wrappedValue.path = "/weather"
                        }
                    }) {
                        Image(systemName: "chevron.backward")
                            .font(.system(size: 20, weight: .bold, design: .rounded))
                    }
                    .buttonStyle(PlainButtonStyle())

                    Spacer()
                }
                Spacer()
            }
            .padding()
        }
    }
}

Custom Transition Animation

To customize the transition animations, you must first extend AnyTransition.

public extension AnyTransition {

    struct NavigationFrontModifier: ViewModifier {
        let offset: CGSize
        public func body(content: Content) -> some View {
            ZStack {
                Color(UIColor.systemBackground)
                content
            }
            .offset(offset)
        }
    }

    static var navigationFront: AnyTransition {
        AnyTransition.modifier(
            active: NavigationFrontModifier(offset: CGSize(width: UIScreen.main.bounds.width, height: 0)),
            identity: NavigationFrontModifier(offset: .zero)
        )
    }

    struct NavigationBackModifier: ViewModifier {
        let opacity: Double
        let offset: CGSize
        public func body(content: Content) -> some View {
            ZStack {
                content
                    .offset(offset)
                Color.black.opacity(opacity)
            }
        }
    }
    
    static var navigationBack: AnyTransition {
        AnyTransition.modifier(
            active: NavigationBackModifier(opacity: 0.17, offset: CGSize(width: -UIScreen.main.bounds.width / 3, height: 0)),
            identity: NavigationBackModifier(opacity: 0, offset: .zero)
        )
    }
}

Next, we will extend Binding.

public extension Binding where Value == Navigator {

    func push<Result>(_ animation: Animation? = .default, _ body: () throws -> Result) rethrows -> Result {
        let insertion: AnyTransition = .navigationFront
        let removal: AnyTransition = .navigationBack
        let transition: AnyTransition = .asymmetric(insertion: insertion, removal: removal)
        self.wrappedValue.zIndex = 0
        self.wrappedValue.transition = transition
        self.wrappedValue.uuid = UUID()
        return try withAnimation(animation, body)
    }

    func pop<Result>(_ animation: Animation? = .default, _ body: () throws -> Result) rethrows -> Result {
        let insertion: AnyTransition = .navigationBack
        let removal: AnyTransition = .navigationFront
        let transition: AnyTransition = .asymmetric(insertion: insertion, removal: removal)
        self.wrappedValue.zIndex = 1
        self.wrappedValue.transition = transition
        self.wrappedValue.uuid = UUID()
        return try withAnimation(animation, body)
    }
}

It can be called as follows

navigator.push {
    navigator.wrappedValue.path = "/weather/\(data.label)"
}

navigator.pop {
    navigator.wrappedValue.path = "/weather"
}
You might also like...
FlowStacks allows you to hoist SwiftUI navigation and presentation state into a Coordinator

FlowStacks allow you to manage complex SwiftUI navigation and presentation flows with a single piece of state. This makes it easy to hoist that state into a high-level coordinator view. Using this pattern, you can write isolated views that have zero knowledge of their context within the navigation flow of an app.

Path based routing in SwiftUI

Easy and maintainable app navigation with path based routing for SwiftUI. With SwiftUI Router you can power your SwiftUI app with path based routing.

Coordinators in SwiftUI. Simple, powerful and elegant.
Coordinators in SwiftUI. Simple, powerful and elegant.

Simple, powerful and elegant implementation of the Coordinator pattern in SwiftUI. Stinsen is written using 100% SwiftUI which makes it work seamlessl

An alternative SwiftUI NavigationView implementing classic stack-based navigation giving also some more control on animations and programmatic navigation.
An alternative SwiftUI NavigationView implementing classic stack-based navigation giving also some more control on animations and programmatic navigation.

swiftui-navigation-stack An alternative SwiftUI NavigationView implementing classic stack-based navigation giving also some more control on animations

🧭 SwiftUI navigation done right

🧭 NavigationKit NavigationKit is a lightweight library which makes SwiftUI navigation super easy to use. 💻 Installation 📦 Swift Package Manager Usi

Navigation helpers for SwiftUI applications build with ComposableArchitecture
Navigation helpers for SwiftUI applications build with ComposableArchitecture

Swift Composable Presentation 📝 Description Navigation helpers for SwiftUI applications build with ComposableArchitecture. More info about the concep

Make SwiftUI Navigation be easy

VNavigator VNavigator is a clean and easy-to-use navigation in SwiftUI base on UINavigationController in UIKit Installation From CocoaPods CocoaPods i

Tools for making SwiftUI navigation simpler, more ergonomic and more precise.
Tools for making SwiftUI navigation simpler, more ergonomic and more precise.

SwiftUI Navigation Tools for making SwiftUI navigation simpler, more ergonomic and more precise. Motivation Tools Navigation overloads Navigation view

SwiftUINavigation provides UIKit-like navigation in SwiftUI

SwiftUINavigation About SwiftUINavigation provides UIKit-like navigation in Swif

Owner
1amageek
@1amageek
1amageek
An open source library for building deep-linkable SwiftUI applications with composition, testing and ergonomics in mind

Composable Navigator An open source library for building deep-linkable SwiftUI applications with composition, testing and ergonomics in mind Vanilla S

Bahn-X 539 Jan 8, 2023
NavigationViewKit is a NavigationView extension library for SwiftUI.

NavigationViewKit 中文版说明 NavigationViewKit is a NavigationView extension library for SwiftUI. For more detailed documentation and demo, please visit 用N

东坡肘子 74 Dec 28, 2022
SwiftUINavigator: a lightweight, flexible, and super easy library which makes SwiftUI navigation a trivial task

The logo is contributed with ❤️ by Mahmoud Hussein SwiftUINavigator is a lightwe

OpenBytes 22 Dec 21, 2022
A view that shows selectable symbols, similar to UITableView's `sectionIndexTitles` API but with support for symbols and more flexibility

?? TableOfContentsSelector Are you familiar with UITableView's sectionIndexTitles API? The little alphabet on the side of some tables for quickly jump

Christian Selig 106 Dec 19, 2022
An iOS view-controller navigation management. No inherit, using one line code to integrate.

KGNavigationBar Example An iOS view-controller navigation management. No inherit, using one line code to integrate. 一个 iOS 控制器导航管理库. 无需继承, 一行代码即可实现集成。

VanJay 5 Sep 6, 2021
Easily hide and show a view controller's navigation bar (and tab bar) as a user scrolls

HidingNavigationBar An easy to use library (written in Swift) that manages hiding and showing a navigation bar as a user scrolls. Features Usage Custo

Tristan Himmelman 1k Dec 21, 2022
A drop-in universal library helps you to manage the navigation bar styles and makes transition animations smooth between different navigation bar styles

A drop-in universal library helps you to manage the navigation bar styles and makes transition animations smooth between different navigation bar styles while pushing or popping a view controller for all orientations. And you don't need to write any line of code for it, it all happens automatically.

Zhouqi Mo 3.3k Dec 21, 2022
iOS UI library to show and hide an extension to your UINavigationBar

ADNavigationBarExtension is a UI library written in Swift. It allows you to show and hide an extension to your UINavigationBar Features Use Extensible

FABERNOVEL 58 Aug 29, 2022
custom navigationBar in swiftui

SwiftUI-WRNavigationBar custom navigationBar in swiftui Requirements iOS 14.0 Installation pod 'SwiftUI-WRNavigationBar', '~>1.1.1' Overview debug cus

wangrui460 29 Nov 7, 2022
sRouting - The lightweight navigation framework for SwiftUI.

sRouting The lightweight navigation framework for SwiftUI. Overview sRouting using the native navigation mechanism in SwiftUI. It's easy to handle nav

Shiro 8 Aug 15, 2022