You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

2023年SwiftUI:无需NavigationStack移除列表NavigationLink Chevron的更优方案

移除SwiftUI列表中NavigationLink的Chevron(不使用NavigationStack的简洁方案)

我想找一种比现有方案更简洁的方法,在不使用NavigationStack的前提下,移除SwiftUI列表里NavigationLink自带的Chevron。现有的方案要么代码冗长,要么性能不如标准实现,以下是我的测试代码和优化后的最终方案。

初始测试代码

import SwiftUI

struct FakeCar: Identifiable, Hashable {
    let id = UUID().uuidString
    let name: String
}


struct DevelopingView: View {

    let test: [FakeCar] = [
        FakeCar(name: "car 1"),
        FakeCar(name: "car 2")
    ]

    @State private var tappedItem: FakeCar?

    var body: some View {
        
        NavigationView {
            List {
                // 带Chevron的标准写法,这是我要避免的
                Section (header: Text("Base")) {
                    ForEach(test) { item in
                        NavigationLink(destination: Text("destination: \(item.name)") ) {
                            Text(item.name)
                        }
                    }
                }
                
                // 苹果论坛的方案,但因为NavigationLink的原因,VStack里的元素无法垂直居中
                // ✅ 我优化后的版本:移除默认Chevron,给空NavigationLink加透明度和frame,配合VStack调整布局
                Section (header: Text("test 1 - ✅ solution")) {
                    ForEach(test) { item in
                        ZStack {
                            VStack(alignment: .leading, spacing: 0) {
                                NavigationLink(destination: Text("destination: \(item.name)")) { EmptyView() }
                                    .opacity(0.0)
                                    .frame(height:0)
                                Text(item.name)
                            }
                        }
                    }
                }

                Section (header: Text("test 1.1 - ✅✅ better solution")) {
                    ForEach(test, id: \.self) { item in
                        ZStack(alignment: .leading) {
                            NavigationLink(destination: Text("destination: \(item.name)")) {
                                EmptyView()
                            }
                            .opacity(0)
                            Text(item.name)
                        }
                    }
                }
                
                // 另一种测试方案,但元素会居中,不知道怎么调整布局
                Section (header: Text("test 2")) {
                    ForEach(test, id: \.self) { item in
                        ZStack {
                            NavigationLink(destination: Text("destination: \(item.name)")) {
                                EmptyView()
                            }
                            .opacity(0)
                            .buttonStyle(PlainButtonStyle())

                            Text(item.name)
                        }
                    }
                }

            }
        }
        // Stack上的方案,能用但代码冗长且不直观
        NavigationView{
            List{
                ForEach(test) { item in
                    Button(action: { tappedItem = item }) {   // << 触发跳转!!
                        Text("Select: \(item.name)")
                            .padding(.vertical,3)
                    }
                }
            }
            .background(
                NavigationLink(destination: Text("MessageDetailView \(tappedItem?.name ?? "N/D")"),
                               isActive: Binding(
                                get: { tappedItem != nil },         // << 控制激活状态!!
                                set: { _,_ in tappedItem = nil }
                               )){
                                   EmptyView()
                               }
            )
        }
    }
}



// 让String遵循Identifiable协议
extension String: Identifiable {
    public typealias ID = Int
    public var id: Int {
        return hash
    }
}

优化后的最终代码

基于Sweeper方案进一步优化后的实现:

NavigationView {
            
            List {
                
                Section(header: Text("Available")) {
                    if classFromEntryPoint.availableApps.isEmpty {
                        Text("No app Available")
                    } else {
                        ForEach(classFromEntryPoint.availableApps) { app in
                            ZStack(alignment: .leading) {
                                VStack(alignment: .leading, spacing: 0) {
                                    NavigationLink(destination: StoreAppDetailView(selectedApp: app)) { EmptyView() }
                                        .opacity(0.0)
                                    RowCell(app: app)
                                }
                            }
                        }
                    }
                }
}
}

内容的提问来源于stack exchange,提问作者biggreentree

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 10:02:07