iosswiftswiftui

Anyone know how properly deal with safe area of the screen?


Anyone know how to properly deal with the blur section at the bottom of the screen? I tried using ZStack but It did not work. The HomePageView() is a ScrollView without any modifier like .ignoreSafeArea() etc. I also have a problem when scrolling to the bottom of the list, the content of the ScrollView overflow to the system UI, how do I fix these problems?

HomePageView :

var body: some View {
        NavigationStack {
            ScrollView {
                VStack {
                    HStack {
                        Image("AppLogo")
                            .resizable()
                            .frame(width: 60, height: 60)
                        Text("Petstagram")
                            .font(Theme.Fonts.h4)
                            .offset(x:-15)
                            .padding()
                        Spacer()
                    }
                    ForEach(viewModel.posts) { post in
                        PostElementView(post: post, viewModel: viewModel)
                    }
                }
                .padding(.horizontal)
                .navigationBarTitleDisplayMode(.inline)
            }
            .scrollIndicators(.hidden)
            .refreshable {
                viewModel.fetchPosts()
            }
        }
    }

ContentView:

TabView(selection: $selectedTab) {
        HomePageView()
            .tag(0)
        
        SelectPicturePageView()
            .tag(1)
        
        ProfilePageView()
            .tag(2)
    }
    .safeAreaPadding(.bottom)
    .safeAreaInset(edge: .bottom) {
        CustomTabBar(selectedTab: $selectedTab)
    }

CustomTabBar:

var body: some View {
        HStack {
            TabButton(imageName: selectedTab == 0 ? "PawFilled" : "Paw",
                      isSelected: selectedTab == 0) {
                selectedTab = 0
            }
            
            Spacer()
            
            TabButton(imageName: selectedTab == 1 ? "plus.app.fill" : "plus.app",
                      isSelected: selectedTab == 1) {
                selectedTab = 1
            }
            
            Spacer()
            
            TabButton(imageName: selectedTab == 2 ? "PersonFilled" : "Person",
                      isSelected: selectedTab == 2) {
                selectedTab = 2
            }
        }
        .padding(.bottom, 16)
        .padding(.vertical, 16)
        .padding(.horizontal, 30)
        .frame(height: 60)
        .frame(maxWidth: .infinity)
        .background(
            RoundedRectangle(cornerRadius: 15)
                .fill(Color(.white))
                .shadow(color: Color.black.opacity(0.2), radius: 5, x: 0, y: -2)
        )
    }

enter image description here


Solution

  • There are a few problems to be resolved:

    1. The translucent background that you are seeing below your custom tab bar is the native tab bar for the TabView. This is still being shown, even though the buttons are empty.

    → To fix, add .toolbarVisibility(.hidden, for: .tabBar) to each of the child views:

    // ContentView
    
    TabView(selection: $selectedTab) {
        HomePageView()
            .toolbarVisibility(.hidden, for: .tabBar) // šŸ‘ˆ added
            .tag(0)
    
        SelectPicturePageView()
            .toolbarVisibility(.hidden, for: .tabBar) // šŸ‘ˆ added
            .tag(1)
    
        ProfilePageView()
            .toolbarVisibility(.hidden, for: .tabBar) // šŸ‘ˆ added
            .tag(2)
    }
    
    1. The content of the scroll view is scrolling through the safe area.

    → To fix, add a small amount of padding below the TabView, to break the contact with the safe area. One pixel is sufficient. You were using .safeAreaPadding before, but it needs to be normal padding:

    // ContentView
    
    @Environment(\.pixelLength) private var pixelLength // šŸ‘ˆ add
    
    TabView(selection: $selectedTab) {
        // ... as above
    }
    .padding(.bottom, pixelLength) // šŸ‘ˆ added
    // .safeAreaPadding(.bottom) // šŸ‘ˆ probably not needed
    .safeAreaInset(edge: .bottom) {
        CustomTabBar(selectedTab: $selectedTab)
    }
    
    1. The background of the custom tab bar is not covering the safe area inset.

    → To fix, use an UnevenRoundedRectangle as background, where only the top corners are rounded. Then add .ignoresSafeArea():

    // CustomTabBar
    
    HStack {
        // ... content as before
    }
    .background { // šŸ‘ˆ changed
        UnevenRoundedRectangle(topLeadingRadius: 15, topTrailingRadius: 15)
            .fill(.white)
            .shadow(color: .black.opacity(0.2), radius: 5, x: 0, y: -2)
            .ignoresSafeArea()
    }