SwiftUI中List内ProgressView仅首次触发显示的问题咨询
解决SwiftUI List中ProgressView二次点击不显示的问题
这不是SwiftUI的Bug,根源在于List底层依赖的UIKit UITableView单元格重用机制。当你切换inProgress状态,从按钮切到进度条再切回按钮时,第二次切换到进度条时,List可能会复用之前的按钮单元格,没有正确重建进度条视图,导致ProgressView不显示。而VStack没有这种重用逻辑,所以每次都能正常刷新。
解决方案一:给条件视图添加唯一ID
通过给按钮和进度条分别设置唯一ID,让List明确识别这是两个不同的视图,避免重用:
struct ContentView: View { @State var inProgress = false var body: some View { List { if inProgress { HStack { Text("Waiting...") ProgressView() } .id("progress-view") } else { Button("Click Me") { inProgress = true Task { try? await Task.sleep(nanoseconds: UInt64(2 * 1_000_000_000)) inProgress = false } } .id("button-view") } } } }
解决方案二:复用同一单元格,通过隐藏切换
把按钮和进度条放在同一个容器内,用opacity控制显示状态,避免List切换单元格:
struct ContentView: View { @State var inProgress = false var body: some View { List { HStack { Group { Text("Waiting...") ProgressView() } .opacity(inProgress ? 1 : 0) Button("Click Me") { inProgress = true Task { try? await Task.sleep(nanoseconds: UInt64(2 * 1_000_000_000)) inProgress = false } } .opacity(inProgress ? 0 : 1) } } } }
解决方案三:替换List为ScrollView+LazyVStack
如果不需要List的编辑、滑动删除等特性,直接用ScrollView搭配LazyVStack替代List,彻底避开单元格重用问题:
struct ContentView: View { @State var inProgress = false var body: some View { ScrollView { LazyVStack { if inProgress { HStack { Text("Waiting...") ProgressView() } } else { Button("Click Me") { inProgress = true Task { try? await Task.sleep(nanoseconds: UInt64(2 * 1_000_000_000)) inProgress = false } } } } } } }
内容的提问来源于stack exchange,提问作者OMGPOP
相关产品推荐
相关产品推荐

