Created
October 15, 2020 21:15
-
-
Save Inncoder/04cf4d5cf200a27039aa80fd3242008f to your computer and use it in GitHub Desktop.
Custom Tab Bar
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
| // | |
| // DarkTabBar.swift | |
| // Animations | |
| // | |
| // Created by Inncoder on 10/10/2020. | |
| // Copyright © 2020 Inncoder AS. All rights reserved. | |
| // | |
| import SwiftUI | |
| struct DarkTabBar: View { | |
| @ObservedObject var viewRouter: ViewRouter | |
| var body: some View { | |
| ZStack { | |
| RoundedRectangle(cornerRadius: tabCornerRadius) | |
| .frame(width: tabSizeWidth, height: tabSizeHeight) | |
| ZStack { | |
| Rectangle() | |
| .frame(width: 70, height: tabSizeHeight) | |
| .background(gradientColor) | |
| .opacity(0.5) | |
| .mask(lightShape()) | |
| RoundedRectangle(cornerRadius: tabCornerRadius) | |
| .frame(width: 45, height: 5) | |
| .foregroundColor(.white) | |
| .offset(x: 0, y: -tabSizeHeight / 2) | |
| } | |
| .offset(x: calcLightOffset(route: viewRouter.currentView), y: 0) | |
| .animation(Animation.easeInOut) | |
| HStack(spacing: (tabSizeWidth - (tabItemSize * CGFloat(Route.allCases.count))) / CGFloat(Route.allCases.count)) { | |
| ForEach(0..<Route.allCases.count, id: \.self) { i in | |
| Button(action: { | |
| viewRouter.currentView = Route.allCases[i] | |
| }, label: { | |
| Image(systemName: viewRouter.imageName(route: Route.allCases[i])) | |
| .resizable() | |
| .frame(width: tabItemSize, height: tabItemSize) | |
| .foregroundColor(Route.allCases[i] == viewRouter.currentView ? .white : Color(UIColor.darkGray)) | |
| .animation(Animation.easeInOut) | |
| }) | |
| } | |
| } | |
| } | |
| .mask(RoundedRectangle(cornerRadius: tabCornerRadius).frame(width: tabSizeWidth, height: tabSizeHeight)) | |
| } | |
| //MARK: - Drawing constants | |
| let gradientColor = LinearGradient(gradient: Gradient(colors: [.white, .clear]), startPoint: .top, endPoint: .bottom) | |
| let tabCornerRadius: CGFloat = 15 | |
| let tabSizeWidth: CGFloat = 350 | |
| let tabSizeHeight: CGFloat = 65 | |
| let tabItemSize: CGFloat = 25 | |
| func calcLightOffset(route: Route) -> CGFloat { | |
| let spacing = (tabSizeWidth - (tabItemSize * CGFloat(Route.allCases.count))) / CGFloat(Route.allCases.count) | |
| let offset = spacing + tabItemSize | |
| switch route { | |
| case .home: | |
| return -(offset * 2) | |
| case .search: | |
| return -offset | |
| case .add: | |
| return 0 | |
| case .likes: | |
| return offset | |
| case .account: | |
| return offset * 2 | |
| } | |
| } | |
| } | |
| struct lightShape: Shape { | |
| func path(in rect: CGRect) -> Path { | |
| var path = Path() | |
| let part = rect.maxX / 4 | |
| path.move(to: CGPoint(x: rect.minX, y: rect.maxY)) | |
| path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY)) | |
| path.addLine(to: CGPoint(x: rect.maxX - part, y: rect.minY)) | |
| path.addLine(to: CGPoint(x: rect.minX + part, y: rect.minY)) | |
| path.closeSubpath() | |
| return path | |
| } | |
| } | |
| struct DarkTabBar_Previews: PreviewProvider { | |
| static var previews: some View { | |
| DarkTabBar(viewRouter: ViewRouter()) | |
| } | |
| } |
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
| // | |
| // MainView.swift | |
| // Animations | |
| // | |
| // Created by Inncoder on 10/10/2020. | |
| // Copyright © 2020 Inncoder AS. All rights reserved. | |
| // | |
| import SwiftUI | |
| struct MainView: View { | |
| @ObservedObject var viewRouter = ViewRouter() | |
| var body: some View { | |
| ZStack { | |
| offWhite.edgesIgnoringSafeArea(.all) | |
| switch viewRouter.currentView { | |
| case .home: | |
| TestView(text: "Home") | |
| case .search: | |
| TestView(text: "Search") | |
| case .add: | |
| TestView(text: "Add") | |
| case .likes: | |
| TestView(text: "Likes") | |
| case .account: | |
| TestView(text: "Account") | |
| } | |
| VStack { | |
| Spacer() | |
| DarkTabBar(viewRouter: viewRouter) | |
| } | |
| } | |
| } | |
| //MARK: - Drawing constants | |
| let offWhite = Color(red: 225 / 255, green: 225 / 255, blue: 235 / 255) | |
| } | |
| struct MainView_Previews: PreviewProvider { | |
| static var previews: some View { | |
| MainView() | |
| } | |
| } |
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
| // | |
| // ViewRouter.swift | |
| // Animations | |
| // | |
| // Created by Inncoder on 10/10/2020. | |
| // Copyright © 2020 Inncoder AS. All rights reserved. | |
| // | |
| import SwiftUI | |
| class ViewRouter: ObservableObject { | |
| @Published var currentView: Route = Route.home | |
| func imageName(route: Route) -> String { | |
| switch route { | |
| case .home: | |
| return "house.fill" | |
| case .search: | |
| return "magnifyingglass" | |
| case .add: | |
| return "plus.app" | |
| case .likes: | |
| return "heart" | |
| case .account: | |
| return "person.fill" | |
| } | |
| } | |
| } | |
| enum Route: CaseIterable { | |
| case home | |
| case search | |
| case add | |
| case likes | |
| case account | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment