Skip to content

Commit

Permalink
Merge pull request #483 from shimastripe/feature/bottom-floating-tabb…
Browse files Browse the repository at this point in the history
…ar-ios

Impl bottom floating material glassed tabbar in iOS
  • Loading branch information
shin-usu authored Aug 16, 2024
2 parents a1a0fdc + 30dd130 commit 16d2480
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 91 deletions.
2 changes: 2 additions & 0 deletions app-ios/Sources/AboutFeature/AboutView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
16 changes: 0 additions & 16 deletions app-ios/Sources/App/RootReducer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -75,10 +74,6 @@ public struct RootReducer {
case favorite(StackActionOf<RootReducer.Path.Favorite>)
case about(StackActionOf<RootReducer.Path.About>)
}

public enum View {
case sameTabTapped(DroidKaigiAppTab)
}
}

public var body: some ReducerOf<Self> {
Expand Down Expand Up @@ -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
}
Expand Down
153 changes: 78 additions & 75 deletions app-ios/Sources/App/RootView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import TimetableFeature
import EventMapFeature
import Theme

public enum DroidKaigiAppTab {
public enum DroidKaigiAppTab: Hashable {
case timetable
case map
case favorite
Expand All @@ -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,
Expand All @@ -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(
Expand All @@ -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):
Expand All @@ -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):
Expand All @@ -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):
Expand All @@ -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
}
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions app-ios/Sources/EventMapFeature/EventMapView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions app-ios/Sources/FavoriteFeature/FavoriteView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ public struct FavoriteView: View {
}
}
.padding(.horizontal, 16)
// bottom floating tabbar padding
Color.clear.padding(.bottom, 60)
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions app-ios/Sources/TimetableFeature/TimetableListView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
}
Expand Down

0 comments on commit 16d2480

Please sign in to comment.