From b02f3fe09ddc0819a869a0e7febcfdf4f12d51a5 Mon Sep 17 00:00:00 2001 From: Go Takagi <15936908+shimastripe@users.noreply.github.com> Date: Thu, 15 Aug 2024 20:19:40 +0900 Subject: [PATCH 1/3] Impl bottom floating material glassed tabbar --- app-ios/Sources/AboutFeature/AboutView.swift | 2 + app-ios/Sources/App/RootView.swift | 153 +++++++++--------- .../EventMapFeature/EventMapView.swift | 2 + .../FavoriteFeature/FavoriteView.swift | 2 + app-ios/Sources/StaffFeature/StaffView.swift | 2 + .../TimetableFeature/TimetableListView.swift | 2 + 6 files changed, 88 insertions(+), 75 deletions(-) diff --git a/app-ios/Sources/AboutFeature/AboutView.swift b/app-ios/Sources/AboutFeature/AboutView.swift index d1bfa3969..e38b97747 100644 --- a/app-ios/Sources/AboutFeature/AboutView.swift +++ b/app-ios/Sources/AboutFeature/AboutView.swift @@ -206,6 +206,8 @@ public struct AboutView: View { .padding(.bottom, 16) } .padding(.horizontal, 16) + // bottom floating tabbar padding + Color.clear.padding(.bottom, 60) } .background(AssetColors.Surface.surface.swiftUIColor) } diff --git a/app-ios/Sources/App/RootView.swift b/app-ios/Sources/App/RootView.swift index c5b3bf297..1aff7848f 100644 --- a/app-ios/Sources/App/RootView.swift +++ b/app-ios/Sources/App/RootView.swift @@ -12,7 +12,7 @@ import TimetableFeature import EventMapFeature import Theme -public enum DroidKaigiAppTab { +public enum DroidKaigiAppTab: Hashable { case timetable case map case favorite @@ -30,67 +30,19 @@ public struct RootView: View { } public var body: some View { - TabView( - selection: Binding( - get: { selection }, - set: { - if selection != $0 { - selection = $0 - return - } - store.send(.view(.sameTabTapped($0))) - } - ) - ) { - Group { + Group { + switch selection { + case .timetable: timetableTab - .tag(DroidKaigiAppTab.timetable) - .tabItem { - Label( - title: { Text("Timetable") }, - icon: { Image(.icTimetable).renderingMode(.template) } - ) - } - + case .map: eventMapTab - .tag(DroidKaigiAppTab.map) - .tabItem { - Label( - title: { Text("Event Map") }, - icon: { Image(.icMap).renderingMode(.template) } - ) - } - + case .favorite: favoriteTab - .tag(DroidKaigiAppTab.favorite) - .tabItem { - Label( - title: { Text("Favorite") }, - icon: { Image(.icFav).renderingMode(.template) } - ) - } - + case .about: aboutTab - .tag(DroidKaigiAppTab.about) - .tabItem { - Label( - title: { Text("About") }, - icon: { Image(.icInfo).renderingMode(.template) } - ) - } - - Text("ID Card Feature") - .tag(DroidKaigiAppTab.idCard) - .tabItem { - Label( - title: { Text("ID Card") }, - icon: { Image(.icProfileCard).renderingMode(.template) } - ) - } + case .idCard: + idCardTab } - .toolbarBackground(AssetColors.Surface.surface.swiftUIColor, for: .tabBar) - // If there are not this code, tab bar color is clear when scroll down to edge. - .toolbarBackground(.visible, for: .tabBar) } .navigationBarTitleStyle( color: AssetColors.Surface.onSurface.swiftUIColor, @@ -99,6 +51,33 @@ public struct RootView: View { ) } + @MainActor + @ViewBuilder + private var tabItems: some View { + let items: [(tab: DroidKaigiAppTab, icon: ImageResource)] = [ + (tab: .timetable, icon: .icTimetable), + (tab: .map, icon: .icMap), + (tab: .favorite, icon: .icFav), + (tab: .about, icon: .icInfo), + (tab: .idCard, icon: .icProfileCard), + ] + HStack(spacing: 36) { + ForEach(items, id: \.tab) { item in + let isSelected = selection == item.tab + Button { + selection = item.tab + } label: { + Image(item.icon).renderingMode(.template).tint(isSelected ? nil : .white) + } + } + } + .padding(.vertical) + .padding(.horizontal, 24) + .background(.ultraThinMaterial, in: Capsule()) + .overlay(Capsule().stroke(.gray, lineWidth: 1)) + .environment(\.colorScheme, .dark) + } + @MainActor private var timetableTab: some View { NavigationStack( @@ -107,12 +86,15 @@ public struct RootView: View { action: \.paths.timetable ) ) { - TimetableView( - store: store.scope( - state: \.timetable, - action: \.timetable + ZStack(alignment: .bottom) { + TimetableView( + store: store.scope( + state: \.timetable, + action: \.timetable + ) ) - ) + tabItems + } } destination: { store in switch store.case { case let .timetableDetail(store): @@ -132,12 +114,15 @@ public struct RootView: View { action: \.paths.about ) ) { - AboutView( - store: store.scope( - state: \.about, - action: \.about + ZStack(alignment: .bottom) { + AboutView( + store: store.scope( + state: \.about, + action: \.about + ) ) - ) + tabItems + } } destination: { store in switch store.case { case let .staff(store): @@ -163,12 +148,15 @@ public struct RootView: View { action: \.paths.favorite ) ) { - FavoriteView( - store: store.scope( - state: \.favorite, - action: \.favorite + ZStack(alignment: .bottom) { + FavoriteView( + store: store.scope( + state: \.favorite, + action: \.favorite + ) ) - ) + tabItems + } } destination: { store in switch store.case { case let .timetableDetail(store): @@ -180,9 +168,24 @@ public struct RootView: View { @MainActor private var eventMapTab: some View { NavigationStack { - EventMapView(store: Store(initialState: .init(), reducer: { - EventMapReducer() - })) + ZStack(alignment: .bottom) { + EventMapView(store: Store(initialState: .init(), reducer: { + EventMapReducer() + })) + tabItems + } + } + } + + @MainActor + private var idCardTab: some View { + NavigationStack { + ZStack(alignment: .bottom) { + ScrollView { + Text("ID Card Feature") + } + tabItems + } } } } diff --git a/app-ios/Sources/EventMapFeature/EventMapView.swift b/app-ios/Sources/EventMapFeature/EventMapView.swift index 5bf9bdcbb..c79c83dc5 100644 --- a/app-ios/Sources/EventMapFeature/EventMapView.swift +++ b/app-ios/Sources/EventMapFeature/EventMapView.swift @@ -37,6 +37,8 @@ public struct EventMapView: View { EventItem(event: event) } } + // bottom floating tabbar padding + Color.clear.padding(.bottom, 60) } .background(AssetColors.Surface.surface.swiftUIColor) .navigationBarTitleDisplayMode(.large) diff --git a/app-ios/Sources/FavoriteFeature/FavoriteView.swift b/app-ios/Sources/FavoriteFeature/FavoriteView.swift index 9d63e6e6a..7bd521e8d 100644 --- a/app-ios/Sources/FavoriteFeature/FavoriteView.swift +++ b/app-ios/Sources/FavoriteFeature/FavoriteView.swift @@ -37,6 +37,8 @@ public struct FavoriteView: View { } } .padding(.horizontal, 16) + // bottom floating tabbar padding + Color.clear.padding(.bottom, 60) } } } diff --git a/app-ios/Sources/StaffFeature/StaffView.swift b/app-ios/Sources/StaffFeature/StaffView.swift index ff4a70181..13a557efa 100644 --- a/app-ios/Sources/StaffFeature/StaffView.swift +++ b/app-ios/Sources/StaffFeature/StaffView.swift @@ -24,6 +24,8 @@ public struct StaffView: View { } } .padding(16) + // bottom floating tabbar padding + Color.clear.padding(.bottom, 60) } .background(AssetColors.Surface.surface.swiftUIColor) .onAppear { diff --git a/app-ios/Sources/TimetableFeature/TimetableListView.swift b/app-ios/Sources/TimetableFeature/TimetableListView.swift index 10d00fc2f..94dfb876b 100644 --- a/app-ios/Sources/TimetableFeature/TimetableListView.swift +++ b/app-ios/Sources/TimetableFeature/TimetableListView.swift @@ -103,6 +103,8 @@ struct TimetableListView: View { .onAppear { store.send(.view(.onAppear)) }.background(AssetColors.Surface.surface.swiftUIColor) + // bottom floating tabbar padding + Color.clear.padding(.bottom, 60) } } } From 1f86fd15fb5173ba8c06156a98c62fe0dc442355 Mon Sep 17 00:00:00 2001 From: Go Takagi <15936908+shimastripe@users.noreply.github.com> Date: Fri, 16 Aug 2024 19:33:01 +0900 Subject: [PATCH 2/3] Remove the sameTabTapped action because this action is no longer needed --- app-ios/Sources/App/RootReducer.swift | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/app-ios/Sources/App/RootReducer.swift b/app-ios/Sources/App/RootReducer.swift index 3f8570d91..6deccb57c 100644 --- a/app-ios/Sources/App/RootReducer.swift +++ b/app-ios/Sources/App/RootReducer.swift @@ -66,7 +66,6 @@ public struct RootReducer { case timetable(TimetableReducer.Action) case favorite(FavoriteReducer.Action) case about(AboutReducer.Action) - case view(View) case paths(Paths) @CasePathable @@ -75,10 +74,6 @@ public struct RootReducer { case favorite(StackActionOf) case about(StackActionOf) } - - public enum View { - case sameTabTapped(DroidKaigiAppTab) - } } public var body: some ReducerOf { @@ -143,17 +138,6 @@ public struct RootReducer { return .none } - case let .view(.sameTabTapped(tab)): - switch tab { - case .timetable: state.paths.timetable.removeAll() - case .favorite: state.paths.favorite.removeAll() - case .about: state.paths.about.removeAll() - case .map: break - case .idCard: break - } - - return .none - default: return .none } From 30dd13058a6cc3406dfe51439479e252823193cd Mon Sep 17 00:00:00 2001 From: Go Takagi <15936908+shimastripe@users.noreply.github.com> Date: Fri, 16 Aug 2024 19:35:17 +0900 Subject: [PATCH 3/3] Remove unnecessary padding --- app-ios/Sources/StaffFeature/StaffView.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/app-ios/Sources/StaffFeature/StaffView.swift b/app-ios/Sources/StaffFeature/StaffView.swift index 13a557efa..ff4a70181 100644 --- a/app-ios/Sources/StaffFeature/StaffView.swift +++ b/app-ios/Sources/StaffFeature/StaffView.swift @@ -24,8 +24,6 @@ public struct StaffView: View { } } .padding(16) - // bottom floating tabbar padding - Color.clear.padding(.bottom, 60) } .background(AssetColors.Surface.surface.swiftUIColor) .onAppear {