Search code examples
swiftswiftuiswiftui-navigationlinkswiftui-navigationstack

How to make NavigationLink rows clear?


I am trying to make NavigationLink rows transparent in a List while using SwiftUIIntrospect to make the NavigationStack background clear. However, I am encountering an issue where the solution does not compile and takes too much time to process.

This is how the View looks right now:

enter image description here

I want to create a list with NavigationLink rows where the background is completely transparent. The app's UI has a gradient background that should be visible through the rows. I used SwiftUIIntrospect to make the NavigationStack background clear, which worked for the navigation view but not for the NavigationLink rows.

The NavigationLink rows should have a transparent background, displaying the gradient background underneath. However, the NavigationLink rows still show some background, and attempts to modify them result in long compilation times or failure to compile.

While attempting different solutions, I encountered prolonged compilation times, and in some cases, the build failed without providing a clear error message.

I have tried the following:

  1. Setting listRowBackground(Color.clear)

    • This removes the row background but does not make it fully transparent.
  2. Using .scrollContentBackground(.hidden)

    • This hides the default List background but does not affect the row backgrounds.
  3. Applying .background(Color.clear) on RowView and NavigationLink

    • No effect on the row’s appearance.
  4. Using SwiftUIIntrospect on NavigationStack

    • It successfully makes the entire navigation stack background clear, but it does not affect NavigationLink rows.
  5. Forcing background removal via UIKit using SwiftUIIntrospect

.introspect(.navigationStack, on: .iOS(.v16, .v17, .v18)) {
    $0.viewControllers.forEach { controller in
        controller.view.backgroundColor = .clear
    }
}

While this clears the main navigation stack, it does not clear the NavigationLink rows.

Here is a simplified version of my implementation:

import SwiftUI
import SwiftUIIntrospect

let gradientBg = LinearGradient(
    colors: [.teal, .blue],
    startPoint: .top, endPoint: .bottom
)

struct TestView: View {
    @State private var valuesList: [String] = ["Testing1", "Testing2", "Testing3"]
    
    var body: some View {
        ZStack {
            gradientBg
                .ignoresSafeArea()
            
            VStack {
                NavigationStack {
                    List {
                        ForEach(valuesList, id: \.self) { value in
                            NavigationLink(value: value) {
                                RowView(name: value)
                                    .listRowBackground(Color.clear)
                                    .listRowSeparator(.hidden)
                            }
                        }
                    }
                    .scrollContentBackground(.hidden)
                    .navigationDestination(for: String.self) { selectedSong in
                        VersionsView()
                    }
                }
                .introspect(.navigationStack, on: .iOS(.v16, .v17, .v18)) {
                    $0.viewControllers.forEach { controller in
                        controller.view.backgroundColor = .clear
                    }
                }
            }
            .padding()
        }
    }
}

struct RowView: View {
    var name: String
    
    var body: some View {
        ZStack {
            Rectangle()
                .fill(.red)
                .frame(width: 300, height: 75)
                .clipShape(RoundedRectangle(cornerRadius: 20))
                .frame(maxWidth: .infinity)
            
            Text(name)
                .font(.title)
        }
    }
}

How can I ensure that the NavigationLink rows are fully transparent so that the background gradient is visible? Is there an approach using SwiftUIIntrospect or another method that would allow me to achieve this effect without causing compilation issues? Has anyone encountered a similar issue, and how was it resolved?

Any insights or alternative approaches would be greatly appreciated!


Solution

  • listRowBackground is the correct modifier to apply in this case, but you applied it on the wrong thing. It should go on the NavigationLink:

    NavigationLink(value: value) {
        RowView(name: value)
    }
    .listRowBackground(Color.clear)
    .listRowSeparator(.hidden)
    

    because the NavigationLink is the actual view for the list row. RowView is the label for the NavigationLink, not a list row.