iosswiftswiftui

How do I get my mini-player to display above my tab view correctly and adapt my views to it?


I'm having an issue with recreating the Apple Music mini-player that's displayed above the tabs (found in TabView I believe). So far, I think I've got it down correctly, but then I find that my other Swift views are not adapting to the mini-player always being displayed above the tabs, which creates overlapping.

Is there a way to counter this? I'm an absolute beginner and I'm trying to understand it better. I just want it to be able to sit down near the tabs and not overlap content found in other views.

This is my ContentView code.

struct ContentView: View {
    var body: some View {
        ZStack(alignment: .bottom) {
            // Main TabView
            TabView {
                News()
                    .tabItem {
                        Label("News", systemImage: "newspaper")
                    }
                
                Events()
                    .tabItem {
                        Label("Events", systemImage: "calendar")
                    }
                
                Browse()
                    .tabItem {
                        Label("Browse", systemImage: "square.grid.2x2")
                    }
                
                Account()
                    .tabItem {
                       Label("Account", systemImage:"person.crop.circle.fill")
                    }
            }
            
            .safeAreaInset(edge: .bottom) {
                MiniPlayer()
                    .background(.ultraThickMaterial)
                    .cornerRadius(10)
                    .shadow(radius: 1)
                    .frame(maxWidth: .infinity, maxHeight: 60)
                    .padding(.bottom, 55)
            }
        }
    }
}

News view (accessed by the tab button) for example still showcases the mini-player, but the list doesn't adapt to my mini-player. It results in my mini-player overlapping the content at the end of the view. I want this mini-player to be displayed at all times.


Solution

  • You could add additional safe area insets to all tab which value is equal to MiniPlayer's height:

    struct ContentView: View {
        var body: some View {
            ZStack(alignment: .bottom) {
                // Main TabView
                TabView {
                    News()
                        .tabItem {
                            Label("News", systemImage: "newspaper")
                        }
                        .safeAreaPadding(.bottom, 120) // -> additional safe area insets
                    
                    Events()
                        .tabItem {
                            Label("Events", systemImage: "calendar")
                        }
                        .safeAreaPadding(.bottom, 120) // -> additional safe area insets
                    
                    Browse()
                        .tabItem {
                            Label("Browse", systemImage: "square.grid.2x2")
                        }
                        .safeAreaPadding(.bottom, 120) // -> additional safe area insets
                    
                    Account()
                        .tabItem {
                           Label("Account", systemImage:"person.crop.circle.fill")
                        }
                        .safeAreaPadding(.bottom, 120) // -> additional safe area insets
                }
                
                .safeAreaInset(edge: .bottom) {
                    MiniPlayer()
                        .background(.ultraThickMaterial)
                        .cornerRadius(10)
                        .shadow(radius: 1)
                        .frame(maxWidth: .infinity, maxHeight: 60)
                        .padding(.bottom, 55)
                }
            }
        }
    }