Reputation: 761
in my last question I've asked about a method to achieve the following TabView overlay in SwiftUI:
Thanks again @davidev for the quick support.
I modified the solution with an opportunity to apply conditional view modifier. In this case .overlay().
extension View {
@ViewBuilder
func `if`<Content: View>(_ condition: Bool, content: (Self) -> Content) -> some View {
if condition {
content(self)
}
else {
self
}
}
}
The code snipped above empowered me to implement the conditional toolbar to appear when an observedObject is toggled (e.g. by a switch from read to edit mode):
.if(class.observedObject){ view in
view.overlay(ToolbarFromDavidev())
}
This also works but it's really buggy (e.g. the whole view navigation gets reset and I've limited styling opportunities).
This leads me to my question: Does someone of you have a reference implementation which I can use for my orientation? I would like to solve this with a ZStack that I can position over my TabView that I use for navigation. Like it's shown in the GIF above. However, I'm not able to position the ZStack over the TabView. Already tried stuff like ignoring safe areas etc.
Many Thanks!
Upvotes: 1
Views: 2536
Reputation: 8130
You could overlay the TabView like so:
TabView {
...
}
.overlay(
VStack {
Spacer()
//Your View
.frame(height: /*Height of the TabBar*/)
}
.edgesIgnoringSafeArea(.all)
)
Now it comes down to finding out the height of the TabBar
. Since its dynamic (different iPhone screen sizes) One way would be like so:
@State private var tabBarHeight: CGFloat = .zero
...
TabView {
//NavigationView
.background(
TabBarAccessor { tabBar in tabBarHeight = tabBar.bounds.height }
)
}
.overlay(
VStack {
Spacer()
//Your View
.frame(height: tabBarHeight)
}
.edgesIgnoringSafeArea(.all)
)
Everything together - your code from your first answer modified.
Code:
struct ContentView: View {
@State private var tabBarHeight: CGFloat = .zero
@State var isSelecting : Bool = false
var body: some View {
TabView {
NavigationView {
Text("First Nav Page")
}
.tabItem {
Image(systemName: "house")
Text("Home")
}.tag(0)
.background(
TabBarAccessor { tabBar in tabBarHeight = tabBar.bounds.height }
)
NavigationView {
Text("Second Nav Page")
}
.tabItem {
Image(systemName: "gear")
Text("Settings")
}.tag(1)
Text("No Nav Page")
.tabItem{
Image(systemName: "plus")
Text("Test")
}.tag(2)
}
.overlay(
VStack {
Spacer()
Rectangle()
.foregroundColor(.green)
.frame(height: tabBarHeight)
}
.edgesIgnoringSafeArea(.all)
)
}
}
struct TabBarAccessor: UIViewControllerRepresentable {
var callback: (UITabBar) -> Void
private let proxyController = ViewController()
func makeUIViewController(context: UIViewControllerRepresentableContext<TabBarAccessor>) ->
UIViewController {
proxyController.callback = callback
return proxyController
}
func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<TabBarAccessor>) {
}
typealias UIViewControllerType = UIViewController
private class ViewController: UIViewController {
var callback: (UITabBar) -> Void = { _ in }
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if let tabBar = self.tabBarController {
self.callback(tabBar.tabBar)
}
}
}
}
The TabBarAccessor
code I have found from: Here
Upvotes: 2