2

Like this question, I wanted a shadow above my bottom tab bar, so I created a custom one in a similar fashion. However in both that example and my example (shown below), there is an undesirable sliver of whitespace right above the shadow that is preventing it from layering directly on top of a scrollview.

enter image description here

Notice how "45" is overlayed by whitespace rather than the shadow. Is there any way to remove the whitespace so my shadow can directly overlay the scrollview?

Example Code:

struct ContentView: View {
    @State var selectedTab: Tab = .events

    var body: some View {
        VStack {
            ScrollView {
                ForEach(0..<100, id: \.self) { index in
                    HStack {
                        Spacer()
                        Text("\(index)")
                        Spacer()
                    }

                }
            }

            ZStack {
                Color.white
                    .frame(height: 30)
                    .shadow(color: .gray.opacity(0.2), radius: 1, x: 0, y: -2)

                HStack {
                    BottomTabBarItem(name: "square.stack", selectedName: "square.stack.fill", directedTab: .events, selectedTab: $selectedTab)
                        .padding(.leading, 20)
                    Spacer()
                    BottomTabBarItem(name: "person.3", selectedName: "person.3.fill", directedTab: .groups, selectedTab: $selectedTab)
                    Spacer()
                    BottomTabBarItem(name: "magnifyingglass", selectedName: "magnifyingglass", directedTab: .search, selectedTab: $selectedTab)
                    Spacer()
                    BottomTabBarItem(name: "bell", selectedName: "bell.fill", directedTab: .requests, selectedTab: $selectedTab)
                    Spacer()
                    BottomTabBarItem(name: "person", selectedName: "person.fill", directedTab: .profile, selectedTab: $selectedTab)
                        .padding(.trailing, 20)
                }
            }
        }
    }
}

struct BottomTabBarItem: View {
    let name: String
    let selectedName: String

    let directedTab: Tab
    @Binding var selectedTab: Tab

    private func getWeight() -> Font.Weight {
        if name != "magnifyingglass" {
            return .light
        } else {
            if selectedTab == directedTab {
                return .bold
            } else {
                return .light
            }
        }
     }

     var body: some View {
        Button {
            selectedTab = directedTab
        } label: {
            Image(systemName: selectedTab == directedTab ? selectedName: name)
                .font(.system(size: 20, weight: getWeight()))
                .foregroundColor(.black)
                .opacity(0.85)
        }
    }
}

enum Tab {
    case events
    case requests
    case profile
    case utilities
    case groups
    case search
}

EDIT:

The answer below solved the problem for this minimal example, but for my actual app code, the problem was due to a Spacer in between the ScrollView and the TabBar. When collapsed, the Spacer still had a minimum length, which showed up right above the shadow as whitespace. I changed Spacer to Spacer(minLength:0) to solve this issue.

John Sorensen
  • 710
  • 6
  • 29

1 Answers1

3

In your case all is needed is zero spacing (tested with Xcode 13 / iOS 15)

demo

var body: some View {
    VStack(spacing: 0) {      // << here !!
        ScrollView {
            ForEach(0..<100, id: \.self) { index in
Asperi
  • 228,894
  • 20
  • 464
  • 690
  • This definitely works in this example. The trouble is that this is a minimal reproducible example, and in my actual code it's still not working. If I can't figure it out, I'll edit the question with a different minimal example to capture the other problem – John Sorensen Dec 04 '21 at 20:51
  • It turns out that the problem in my app was caused by a collapsed Spacer at the default minLength. Thanks for your help though! – John Sorensen Dec 05 '21 at 02:23