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

iOS 26+中Large Navigation Title随ScrollView异常滚动问题求解决方案

解决iOS 16+中ScrollView与Large Navigation Title的滚动联动问题

问题复现代码

struct ContentView: View {
    var body: some View {
        NavigationStack {
            VStack {
                
                Rectangle()
                    .foregroundStyle(.red)
                    .frame(width: 100, height: 100)
                
                ScrollView {
                    Text("Text")
                    Text("Text2")
                    Text("Text3")
                }
            }
            .navigationTitle("Large Title")
            .toolbarTitleDisplayMode(.large)
        }
    }
}

从iOS 16开始,无论ScrollView在视图层级中的哪个位置,滚动它都会触发Large Navigation Title的收缩/展开交互。当ScrollView位于屏幕底部时,这种联动会导致布局异常,属于系统已知行为Bug。

可行解决办法

方法1:iOS 17+ 原生API快速解决

iOS 17引入了scrollBehavior修饰符,直接设置为.static即可解除ScrollView与导航栏的滚动联动:

ScrollView {
    Text("Text")
    Text("Text2")
    Text("Text3")
}
.scrollBehavior(.static)

方法2:iOS 16兼容方案(自定义ScrollView)

如果需要兼容iOS 16,可以通过UIViewRepresentable封装一个不触发导航栏交互的ScrollView:

struct NonNavScrollView<Content: View>: UIViewRepresentable {
    let content: Content
    
    init(@ViewBuilder content: () -> Content) {
        self.content = content()
    }
    
    func makeUIView(context: Context) -> UIScrollView {
        let scrollView = UIScrollView()
        // 禁用自动调整contentInset,避免触发导航栏联动
        scrollView.contentInsetAdjustmentBehavior = .never
        
        let hostingView = UIHostingController(rootView: content)
        hostingView.view.translatesAutoresizingMaskIntoConstraints = false
        scrollView.addSubview(hostingView.view)
        
        NSLayoutConstraint.activate([
            hostingView.view.topAnchor.constraint(equalTo: scrollView.topAnchor),
            hostingView.view.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
            hostingView.view.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
            hostingView.view.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
            hostingView.view.widthAnchor.constraint(equalTo: scrollView.widthAnchor)
        ])
        
        return scrollView
    }
    
    func updateUIView(_ uiView: UIScrollView, context: Context) {
        guard let hostingView = uiView.subviews.first as? UIHostingController<Content> else { return }
        hostingView.rootView = content
    }
}

使用时替换原有的ScrollView:

struct ContentView: View {
    var body: some View {
        NavigationStack {
            VStack {
                Rectangle()
                    .foregroundStyle(.red)
                    .frame(width: 100, height: 100)
                
                NonNavScrollView {
                    Text("Text")
                    Text("Text2")
                    Text("Text3")
                }
            }
            .navigationTitle("Large Title")
            .toolbarTitleDisplayMode(.large)
        }
    }
}

方法3:全局修改ScrollView行为(谨慎使用)

如果你的App中所有ScrollView都不需要触发导航栏联动,可以在App结构体中全局设置:

@main
struct YourApp: App {
    init() {
        UIScrollView.appearance().contentInsetAdjustmentBehavior = .never
    }
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

注意:此方法会影响所有ScrollView,包括那些原本需要联动导航栏的场景,需谨慎使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 07:44:52