Search code examples
iosswiftuimapkitsafearea

How to extend a MapKit's Map beyond NavigationBar and TabBar in SwiftUI?


I am working on a SwiftUI app which uses both TabView and NavigationView. One of the views is responsible for presenting a Map from MapKit and it is meant to take all available space. I would like it to extend beyond TabBar and NavigationBar, so that I can see the map's content through the bars' standard translucent material, just like on this screenshot from the Apple Store app:

Apple Store App Screenshot

I tried using .ignoresSafeArea() modifier on the Map, but then the bars had no background material at all, just the buttons and navigation title were visible, like this:

Demo View Screenshot

It doesn't seem to be a problem specific to the structure of my app - I tried making a new, independent view with those two bars and still got the same results. Here is the code of that sample view:

import MapKit
import SwiftUI

struct SwiftUIView: View {
    @State private var region = MKCoordinateRegion(
        center: CLLocationCoordinate2D(latitude: 50, longitude: 20),
        span: MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)
    )
    
    var body: some View {
        TabView {
            NavigationView {
                Map(coordinateRegion: $region)
                    .ignoresSafeArea()
                    .navigationTitle("Map")
            }
            .tabItem {
                Label("Map", systemImage: "map")
            }
        }
    }
}

struct SwiftUIView_Previews: PreviewProvider {
    static var previews: some View {
        SwiftUIView()
    }
}

Is there something important I am missing or is there a bug in the Map component?


Solution

  • You can fix it by adding a ScrollView background:

          ZStack {
          ScrollViewReader { proxy in
            ScrollView {
              Spacer()
                .frame(height: 10000)
                .id(1)
              Spacer()
                .frame(height: 10000)
                .id(2)
              Spacer()
                .frame(height: 10000)
                .id(3)
            }
            .onAppear {
              proxy.scrollTo(2)
            }
          }
          .ignoresSafeArea()
            
            Map(...)
              .ignoresSafeArea()
          }
    

    This makes the toolbar appearance to be as desired - as it is a scroll view that has both top and bottom overlap..