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

SwiftUI中点击NavigationLink跳转后List视图下移的问题求助

SwiftUI List返回后整体向下偏移的解决办法

我用SwiftUI开发搜索视图时遇到一个问题:视图内的List通过ForEach填充数据,每行的NavigationLink跳转到新视图后,点击返回按钮回到原视图时,List会整体向下偏移。

我尝试过将视图嵌套在ScrollView中,但这导致List直接消失(查阅资料得知这是List嵌套ScrollView的正常表现);移除List仅保留ForEach时,导航功能正常,说明问题确实出在List上。我希望继续使用原生List(因其创建Section更便捷),求可行的解决办法。

相关代码

struct SearchView: View {
    @Binding var isSearching : Bool
    @FocusState var isFocused : Bool
    @StateObject var viewModel = SearchVM()
    var body: some View {
        VStack{
            HStack{
                VStack{
                    HStack{
                        Image(systemName: "magnifyingglass")
                            .foregroundStyle(Color.secondaryColor)
                        TextField("Pesquisar...", text: $viewModel.searchText )
                            .focused($isFocused)
                    }.modifier(OutlinedCardStyle(padding: 12))
                    
                }
                .textFont(style: .montserrat14)
                
                
                Button(action: {
                    withAnimation(.easeOut(duration: 0.4)) {
                        isSearching.toggle()
                        isFocused = isSearching
                    }
                }, label: {
                    Text("Cancelar")
                        .bold()
                }).padding(.leading,5)
            }.padding([.horizontal,.top])
            List {
                ForEach($viewModel.matchedSections, id: \.id) { $section in
                    Section($section.sectionName.wrappedValue){
                        ForEach($section.subSections, id: \.id){ subsection in
                            NavigationLink{
                                AppointmentView()
                            }label:{
                                Text(subsection.sectionName.wrappedValue)
                            }
                            
                        }
                    }
                }
               
            } .listStyle(.plain)
                .animation(.smooth, value: viewModel.matchedSections)
                
            
            Spacer()
        }
        .onAppear{
            isFocused = isSearching
        }
    }
}

可行解决办法

  • 调整动画作用范围
    原代码将动画直接绑定在List上,可能和导航跳转的动画产生冲突。可以把动画移到ForEach层级,只针对数据变化的部分执行动画:

    List {
        ForEach($viewModel.matchedSections, id: \.id) { $section in
            Section($section.sectionName.wrappedValue){
                ForEach($section.subSections, id: \.id){ subsection in
                    NavigationLink{
                        AppointmentView()
                    }label:{
                        Text(subsection.sectionName.wrappedValue)
                    }
                }
            }
        }
        .animation(.smooth, value: viewModel.matchedSections) // 动画移至此处
    } .listStyle(.plain)
    
  • 重置焦点状态
    在离开SearchView时重置焦点,避免键盘相关的布局残留导致返回时偏移:

    VStack{
        // ... 原有内容
    }
    .onAppear{
        isFocused = isSearching
    }
    .onDisappear{
        isFocused = false
    }
    
  • 禁止键盘滚动关闭
    给List添加scrollDismissesKeyboard(.never),避免键盘交互引发的布局偏移:

    List {
        // ... 原有内容
    }
    .listStyle(.plain)
    .scrollDismissesKeyboard(.never)
    .animation(.smooth, value: viewModel.matchedSections)
    
  • 固定导航栏样式
    如果SearchView嵌入在NavigationStack中,明确设置导航栏的显示模式,固定其高度:

    VStack{
        // ... 原有内容
    }
    .navigationBarTitleDisplayMode(.inline)
    .navigationBarHidden(false)
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 02:13:26