Hotwire Native iOS - Tabs and design customisation
Add Tab bar #
I think it’s one of the most requested/improtant features for a classic Rails app that is turned mobile.
Tabs behave like browser tabs = navigation history is separete within each tab.
The tab titles will be overriden by the page HTML <title>
if present.
Download and use SF Symbols app to select icons that work best for you.
The best boilerplate to start building a Native app is the Demo app.
// Demo/SceneController.swift
class TabBarController: UITabBarController {
private let navigators: [Navigator]
init(navigators: [Navigator]) {
self.navigators = navigators
super.init(nibName: nil, bundle: nil)
viewControllers = navigators.map { $0.rootViewController }
// Customize tab bar items
viewControllers?[0].tabBarItem = UITabBarItem(title: "Home", image: UIImage(systemName: "house"), tag: 0)
viewControllers?[1].tabBarItem = UITabBarItem(title: "Posts", image: UIImage(systemName: "play.circle"), tag: 1)
viewControllers?[2].tabBarItem = UITabBarItem(title: "Playlists", image: UIImage(systemName: "list.number"), tag: 2)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Assuming you have paths /posts
& /playlists
in your app:
# Demo/SceneController.swift
- private lazy var navigator = Navigator(pathConfiguration: pathConfiguration, delegate: self)
+ private lazy var navigators: [Navigator] = {
+ (0..<3).map { _ in Navigator(pathConfiguration: pathConfiguration, delegate: self) }
+ }()
+ private lazy var tabBarController = TabBarController(navigators: navigators)
...
- navigator.route(rootURL)
+ navigators[0].route(rootURL)
+ navigators[1].route(rootURL.appendingPathComponent("/posts"))
+ navigators[2].route(rootURL.appendingPathComponent("/playlists"))
...
- window.rootViewController = navigator.rootViewController
+ window.rootViewController = tabBarController
⚠️ You might have to delete the example code for “Authentication” and “Numbers”, so that no errors pop up.
Customize tab bar design #
Use uicolor.io to convert Hex colors to Swift.
// Demo/SceneController.swift
extension UITabBar {
static func configureWithOpaqueBackground() {
let tabBarAppearance = UITabBarAppearance()
tabBarAppearance.configureWithOpaqueBackground()
// tabBarAppearance.backgroundColor = .systemGray5
tabBarAppearance.backgroundColor = UIColor(red: 0.09, green: 0.11, blue: 0.13, alpha: 1.00)
appearance().standardAppearance = tabBarAppearance
appearance().scrollEdgeAppearance = tabBarAppearance
}
}
# Demo/SceneController.swift
+ UITabBar.configureWithOpaqueBackground()
window.rootViewController = tabBarController
Customize header #
- Make header not transparent
- Change background color
- Change text color
// Demo/SceneController.swift
extension UINavigationBar {
static func configureWithOpaqueBackground() {
let navigationBarAppearance = UINavigationBarAppearance()
navigationBarAppearance.configureWithOpaqueBackground()
// navigationBarAppearance.backgroundColor = .systemBlue
navigationBarAppearance.backgroundColor = UIColor(red: 0.09, green: 0.11, blue: 0.13, alpha: 1.00)
navigationBarAppearance.titleTextAttributes = [.foregroundColor: UIColor.white]
navigationBarAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.white]
appearance().scrollEdgeAppearance = navigationBarAppearance
appearance().standardAppearance = navigationBarAppearance
}
}
above
# Demo/SceneController.swift
+ UINavigationBar.configureWithOpaqueBackground()
window.rootViewController = tabBarController
Disable force touch #
Force Touch = press and hold a link for a long time to open it as a preview in an in-app browser. This feels like a browser, not app behaviour.
Let’s disable it.
# Demo/SceneController.swift
...
configureBridge()
+ Hotwire.config.makeCustomWebView = { configuration in
+ let webView = WKWebView(frame: .zero, configuration: configuration)
+ webView.allowsLinkPreview = false
+ Bridge.initialize(webView)
+ return webView
+ }
configureRootViewController()
...
Subscribe to SupeRails.com for more Hotwire Native content!
That’s it for now!
Did you like this article? Did it save you some time?