Instantly share code, notes, and snippets.
Last active
February 27, 2025 09:46
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
-
Save Codelaby/52625b07fff3a9f93fcb7aced7cf12ac to your computer and use it in GitHub Desktop.
Navigation UI custom
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // | |
| // TranslucentDemo.swift | |
| // FestivES | |
| // | |
| // Created by Codelaby on 27/2/25. | |
| // | |
| import SwiftUI | |
| // MARK: Translucent | |
| extension UIBlurEffect { | |
| static func effect(blurRadius: CGFloat) -> UIBlurEffect? { | |
| let selector = NSSelectorFromString("effectWithBlurRadius:") | |
| guard self.responds(to: selector) else { return nil } | |
| let blurEffect = self.perform(selector, with: blurRadius).takeUnretainedValue() | |
| return blurEffect as? UIBlurEffect | |
| } | |
| } | |
| /// MARK: For apply all UIViewCront | |
| //extension UIViewController { | |
| // | |
| // var topbarHeight: CGFloat { | |
| // let safeAreaTop: CGFloat = view.safeAreaInsets.top | |
| // | |
| // let statusBarHeight: CGFloat | |
| // if #available(iOS 13.0, *) { | |
| // statusBarHeight = view.window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0.0 | |
| // } else { | |
| // statusBarHeight = UIApplication.shared.statusBarFrame.height | |
| // } | |
| // | |
| // let navigationBarHeight = self.navigationController?.navigationBar.frame.height ?? 0.0 | |
| // print("Status Bar Height: \(statusBarHeight)") | |
| // print("Navigation Bar Height: \(navigationBarHeight)") | |
| // | |
| // return statusBarHeight + navigationBarHeight + safeAreaTop | |
| // } | |
| // | |
| //} | |
| // MARK: Translucent Top Nav bar | |
| struct TranslucentDemo: View { | |
| init() { | |
| // Customize the navigation bar appearance | |
| let standard = UINavigationBarAppearance() | |
| standard.backgroundColor = .clear | |
| standard.backgroundEffect = UIBlurEffect.effect(blurRadius: 22) | |
| standard.shadowColor = .clear | |
| // Apply the appearance to all navigation bar modes | |
| UINavigationBar.appearance().standardAppearance = standard | |
| UINavigationBar.appearance().compactAppearance = standard | |
| UINavigationBar.appearance().scrollEdgeAppearance = standard | |
| } | |
| var body: some View { | |
| NavigationStack { | |
| ScrollView { | |
| ForEach(0..<3) { _ in | |
| ForEach(ColorDemoModel.allItems) { item in | |
| VStack { | |
| HStack { | |
| ForEach(0..<3) { _ in | |
| Spacer() | |
| Rectangle() | |
| .fill(item.color) | |
| .frame(width: 50, height: 50) | |
| } | |
| Spacer() | |
| } | |
| } | |
| } | |
| } | |
| } | |
| .navigationTitle("Navigation Blur") | |
| #if os(iOS) | |
| .navigationBarTitleDisplayMode(.inline) | |
| #endif | |
| } | |
| } | |
| } | |
| #Preview("Nav Bar") { | |
| TranslucentDemo() | |
| } | |
| // MARK: Translucent Nav Bar & Tab nav | |
| struct TranslucentDemo2: View { | |
| @State private var selectedTab: TabEnum = .listBooks | |
| init() { | |
| // HEADER: Customize the navigation bar | |
| if let blurEffect = UIBlurEffect.effect(blurRadius: 22) { | |
| // Customize the navigation bar appearance | |
| let standard = UINavigationBarAppearance() | |
| standard.backgroundColor = .clear | |
| standard.backgroundEffect = blurEffect | |
| standard.shadowColor = .clear | |
| // Apply the appearance to all navigation bar modes | |
| UINavigationBar.appearance().standardAppearance = standard | |
| UINavigationBar.appearance().compactAppearance = standard | |
| UINavigationBar.appearance().scrollEdgeAppearance = standard | |
| } | |
| // FOOTER: Customize the tab bar | |
| if let blurEffect = UIBlurEffect.effect(blurRadius: 22) { | |
| // Customize the tab bar appearance | |
| let tabBarAppearance = UITabBarAppearance() | |
| tabBarAppearance.backgroundColor = .clear | |
| tabBarAppearance.backgroundEffect = blurEffect | |
| tabBarAppearance.shadowColor = .clear | |
| // Apply the appearance to all navigation tab bar modes | |
| UITabBar.appearance().isTranslucent = true | |
| UITabBar.appearance().backgroundColor = .clear | |
| UITabBar.appearance().scrollEdgeAppearance = tabBarAppearance | |
| UITabBar.appearance().standardAppearance = tabBarAppearance | |
| } | |
| } | |
| var body: some View { | |
| TabView(selection: $selectedTab) { | |
| ForEach(TabEnum.allCases) { tab in | |
| NavigationStack { | |
| VStack { | |
| switch tab { | |
| case .listBooks: | |
| SampleList() | |
| case .listMovies: | |
| SampleList() | |
| case .profile: | |
| SampleList() | |
| } | |
| } | |
| .navigationTitle(tab.description) | |
| #if os(iOS) | |
| .navigationBarTitleDisplayMode(.inline) | |
| #endif | |
| } | |
| .tabItem { | |
| Image(systemName: tab.rawValue) | |
| Text(tab.description) | |
| } | |
| } | |
| } | |
| } | |
| enum TabEnum: String, CaseIterable, Identifiable, CustomStringConvertible { | |
| case listBooks = "book.fill" | |
| case listMovies = "movieclapper.fill" | |
| case profile = "person.fill" | |
| var id: Self { self } | |
| var description: String { | |
| return switch self { | |
| case .listBooks: | |
| "Books" | |
| case .listMovies: | |
| "Movies" | |
| case .profile: | |
| "Profile" | |
| } | |
| } | |
| } | |
| } | |
| // MARK: SampleList | |
| struct SampleList: View { | |
| @State private var selectedItem: ColorDemoModel? | |
| var body: some View { | |
| ScrollView { | |
| VStack { | |
| Text("Large Title").font(.largeTitle) | |
| Image("graphic_color") | |
| .resizable() | |
| .scaledToFit() | |
| Group { | |
| Text("Title").font(.title) | |
| Text("Headline").font(.headline) | |
| Text("Subheadline").font(.subheadline) | |
| Text("Body").font(.body) | |
| Text("Callout").font(.callout) | |
| Text("Footnote").font(.footnote) | |
| Text("Caption").font(.caption) | |
| } | |
| .frame(maxWidth: .infinity, alignment: .leading) | |
| .padding(.horizontal) | |
| ForEach(ColorDemoModel.allItems) { item in | |
| VStack { | |
| HStack { | |
| ForEach(0..<3) { _ in | |
| Spacer() | |
| Rectangle() | |
| .fill(item.color) | |
| .frame(width: 80, height: 50) | |
| .cornerRadius(10) | |
| .onTapGesture { | |
| selectedItem = item // Asigna el item seleccionado | |
| } | |
| } | |
| Spacer() | |
| } | |
| } | |
| } | |
| Image("graphic_color") | |
| .resizable() | |
| .scaledToFit() | |
| Group { | |
| Text("Title").font(.title) | |
| Text("Headline").font(.headline) | |
| Text("Subheadline").font(.subheadline) | |
| Text("Body").font(.body) | |
| Text("Callout").font(.callout) | |
| Text("Footnote").font(.footnote) | |
| Text("Caption").font(.caption) | |
| } | |
| .frame(maxWidth: .infinity, alignment: .trailing) | |
| .padding(.horizontal) | |
| ForEach(ColorDemoModel.allItems) { item in | |
| VStack { | |
| HStack { | |
| ForEach(0..<3) { _ in | |
| Spacer() | |
| Rectangle() | |
| .fill(item.color) | |
| .frame(width: 80, height: 50) | |
| .cornerRadius(10) | |
| .onTapGesture { | |
| selectedItem = item // Asigna el item seleccionado | |
| } | |
| } | |
| Spacer() | |
| } | |
| } | |
| } | |
| } | |
| } | |
| .sheet(item: $selectedItem) { item in | |
| ColorDetailView(item: item) | |
| .presentationDetents([.height(250)]) | |
| } | |
| } | |
| } | |
| struct ColorDetailView: View { | |
| let item: ColorDemoModel | |
| @State private var navigationBarHeight: CGFloat = 48 | |
| var body: some View { | |
| NavigationStack { | |
| ScrollView { | |
| VStack(spacing: 20) { | |
| Text(item.title) | |
| .font(.largeTitle) | |
| .bold() | |
| Rectangle() | |
| .fill(item.color) | |
| .frame(width: 200, height: 100) | |
| .cornerRadius(10) | |
| Text("Variant of \(item.title)") | |
| .font(.body) | |
| .multilineTextAlignment(.center) | |
| .padding() | |
| Rectangle() | |
| .fill(item.color.secondary) | |
| .frame(width: 200, height: 100) | |
| .cornerRadius(10) | |
| Rectangle() | |
| .fill(item.color.tertiary) | |
| .frame(width: 200, height: 100) | |
| .cornerRadius(10) | |
| Rectangle() | |
| .fill(item.color.quaternary) | |
| .frame(width: 200, height: 100) | |
| .cornerRadius(10) | |
| Rectangle() | |
| .fill(item.color.quinary) | |
| .frame(width: 200, height: 100) | |
| .cornerRadius(10) | |
| } | |
| .frame(maxWidth: .infinity) | |
| //.toolbarBackground(.hidden, for: .navigationBar) // Hide background nav | |
| } | |
| .navigationTitle("Color Detail") | |
| #if os(iOS) | |
| .navigationBarTitleDisplayMode(.inline) | |
| #endif | |
| } | |
| } | |
| } | |
| #Preview("Nav bar & tab nav") { | |
| TranslucentDemo2() | |
| } | |
| // MARK: Sample Model | |
| struct ColorDemoModel: Identifiable, Hashable, Sendable { | |
| let id: UUID = .init() | |
| let title: String | |
| let summary: String | |
| let color: Color | |
| static let allItems: [ColorDemoModel] = [ | |
| ColorDemoModel(title: "Red", summary: "This is red", color: .red), | |
| ColorDemoModel(title: "Green", summary: "This is green", color: .green), | |
| ColorDemoModel(title: "Blue", summary: "This is blue", color: .blue), | |
| ColorDemoModel(title: "Yellow", summary: "This is yellow", color: .yellow), | |
| ColorDemoModel(title: "Orange", summary: "This is orange", color: .orange), | |
| ColorDemoModel(title: "Pink", summary: "This is pink", color: .pink), | |
| ColorDemoModel(title: "Mint", summary: "This is Mint", color: .mint), | |
| ColorDemoModel(title: "Teal", summary: "This is teal", color: .teal), | |
| ColorDemoModel(title: "Cyan", summary: "This is cyan", color: .cyan), | |
| ColorDemoModel(title: "Indigo", summary: "This is indigo", color: .indigo), | |
| ColorDemoModel(title: "Purple", summary: "This is purple", color: .purple), | |
| ColorDemoModel(title: "Gray", summary: "This is Gray", color: .gray), | |
| ColorDemoModel(title: "Brown", summary: "This is Brown", color: .brown), | |
| ] | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment