2023年SwiftUI:无需NavigationStack移除列表NavigationLink Chevron的更优方案
我想找一种比现有方案更简洁的方法,在不使用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
相关产品推荐
相关产品推荐

